13

I have OS X "El capitan" 10.11.6 and I am using Ansible 2.1.1.0 to run some maintenance tasks on a remote Linux server Ubuntu 16.04 Xenial. I am trying to get the following list of folders sorted on the remote machine (Linux), so I can remove the old ones when needed:

/releases/0.0.0
/releases/0.0.1
/releases/0.0.10
/releases/1.0.0
/releases/1.0.5
/releases/2.0.0

I have been trying with the module find in Ansible, but it returns a not sorted list. Is there an easy way to achieve this with Ansible?

Ander
  • 5,093
  • 7
  • 41
  • 70
  • What do you mean you are "trying to get"? What is your input, what do you want to pass the output to? – techraf Sep 10 '16 at 07:48

4 Answers4

24

You can sort items with sort filter:

- hosts: localhost
  gather_facts: no
  tasks:
    - find: path="/tmp" patterns="test*"
      register: files

    - debug: msg="{{ files.files | sort(attribute='ctime') | map(attribute='path') | list }}"

Just change sort attribute to your need.
But beware that string sort is not numeric, so /releases/1.0.5 will go after /releases/1.0.10.

Konstantin Suvorov
  • 65,183
  • 9
  • 162
  • 193
  • 2
    I didn't know about the jinja2 sort filter, thanks @Konstantin Suvorov. But as you said, this solution doesn't meet the spec. – Ander Sep 10 '16 at 21:08
  • you can sort reverse with `sort(attribute='ctime', reverse=True)` (taken from [here](https://stackoverflow.com/a/39051279/2799887)) – pjvleeuwen Apr 15 '19 at 16:56
9

Interesting solutions, thanks a lot guys. But I think I have found the easiest way in Ubuntu, just using ls -v /releases/ will apply natural sorting to all folders:

- name: List of releases in ascendent order  
  command: ls -v /releases/
  register: releases

- debug: msg={{ releases.stdout_lines }}

The response is:

ok: [my.remote.com] => {
    "msg": [
        "0.0.0",
        "0.0.1",
        "0.0.10",
        "1.0.0",
        "1.0.5",
        "2.0.0"
    ]
}
Ander
  • 5,093
  • 7
  • 41
  • 70
  • Interesting... how is `ls -v` gives you numeric sort? – Konstantin Suvorov Sep 11 '16 at 13:31
  • 1
    Having a look at `ls --help` I just found this: `ls -v` **Natural sort of (version) numbers within text.** – Ander Sep 11 '16 at 20:37
  • I have edited my answer, Originally I wrote "numeric sort" but this is actually **natural sort**. – Ander Sep 11 '16 at 22:09
  • 2
    This will work only with GNU `ls`, not `ls` on a mac. – Konstantin Suvorov Sep 12 '16 at 06:54
  • 1
    You right Konstantin, I was using OS X to run Ansible but the command `ls -v` was actually executed on the remote server **Ubuntu 16.04 Xenial**. It's good to know it won't work on OS X – Ander Sep 12 '16 at 07:14
  • `ls -1 /releases/ | sort -n -k1` works on Linux and Unix systems as well (see https://unix.stackexchange.com/a/34006/335249). As the Ansible `command` module does not support stream operations like `|` you will have to use the `shell` module instead. – heiflo Aug 26 '19 at 08:26
2

If you want to find files older than a period, maybe age and age_stamp parameters of find module can help you. For example:

# Recursively find /tmp files older than 4 weeks and equal or greater than 1 megabyte
- find: paths="/tmp" age="4w" size="1m" recurse=yes
longhua
  • 4,142
  • 21
  • 28
1

It sounds like what you want to do is real simple but the standard ansible modules doesn't quite have what you needed.

As an alternative you can write your own script using your favorite programming language then use the copy module to pass that script to the host and use command to execute it. When done, use file to remove that script.

The downside of it is that the target host will need to have the required executable to run your script. For instance if you are doing a python script then the target host will need python

Example:

- name: Send your script to the target host
  copy: src=directory_for_scripts/my_script.sh dest=/tmp/my_script.sh
- name: Execute my script on target host
  command: >
          /bin/bash /tmp/my_script.sh
- name: Clean up the target host by removing script
  file: path=/tmp/my_script.sh state=absent
Samuel Toh
  • 18,006
  • 3
  • 24
  • 39