【问题标题】:find the latest file that was modified within last minute in ansible?在ansible中找到最后一分钟内修改的最新文件?
【发布时间】:2019-10-04 20:56:50
【问题描述】:

我有一个特定目录中的文件列表,如下所示:

david@host:~/jobs/process/workspace/files$ ls -lrth
total 68K
-rw-r--r-- 1 david david 7.8K Oct  1 11:10 golden_proc.init.1569953435497
-rw-r--r-- 1 david david 7.7K Oct  2 12:11 golden_proc.init.1570043494149
-rw-r--r-- 1 david david 7.7K Oct  2 20:15 golden_proc.init.1570072510929

每个文件名都以时间戳结尾。现在我需要在 ansible 中找到一个刚刚修改或创建的最新文件。

  • 如果没有这样的文件,则在可行的情况下通过记录“找不到任何文件”从 ansible 成功返回。
  • 如果有这样的文件,则将该文件复制到“/tmp”文件夹。
  • 如果在最后一分钟生成或修改了多个文件,则使用最新的。

这可以在ansible中做到吗?我看到 ansible 中有一个 find 模块,但不确定如何使用该模块使上述工作正常工作?

---
- name: Play 1
  hosts: 127.0.0.1
  tasks:
      - name: find the latest file
        find: paths=/var/lib/jobs/workspace/process/files
              file_type=file
              age=-{{ time_window }}m
              age_stamp=mtime
        register: files

【问题讨论】:

    标签: linux ansible


    【解决方案1】:

    这绝对是可能的,你甚至离解决方案很近。

    您可能已经看到它已经对您的find 进行了debug,它的返回包含files 的列表,如果您没有文件,则此列表将为空。

    所以使用 Jinja 可以很容易地查看列表何时为空

    - debug:
        msg: '{{ files.files if files.files|count > 0 else "cannot find any file" }}'
    

    此语法使用inline ifcount filter

    关于您现在想要最新文件这一事实,您还可以使用一组 Jinja 文件管理器:filter sort 将帮助您按修改时间对文件进行排序,filter first 将帮助您仅获取您列出的第一个元素。

    - debug:
        msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path }}'
    

    现在您只需将两者结合在一个长的 Jinja 表达式中:

    - debug:
        msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path if files.files|count > 0 else "cannot find any file" }}'
    

    为了复制文件,您将需要一个额外的特定于 Ansible 的 Jinja 过滤器,即 basename,以便从完整路径中获取文件名

    - debug:
        msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path | basename if files.files|count > 0 else "cannot find any file" }}'
    

    但您还需要when 语句,因此如果没有匹配的文件,您的副本将被跳过:

    - name: Copy file, if found                 
      copy:
        src: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path }}'
        dest: '/tmp/{{ (files.files | sort(attribute="mtime", reverse=true) | first).path | basename }}'
      when: files.files|count > 0
    

    供您测试的完整工作手册:

    ---
    - hosts: localhost
      connection: locale
    
      vars:
        var_files:
          - { 'name': 'a', 'time': 86400 }
          - { 'name': 'b', 'time': 30 }
          - { 'name': 'c', 'time': 20 }
    
      tasks:
        - name: creating a bunch of matching files
          file:
            path: '/data/{{ item.name }}'
            state: touch
          with_items: '{{ var_files }}'
    
        - name: aging those files
          file:
            path: '/data/{{ item.name }}'
            modification_time: '{{ "%Y%m%d%H%M.%S" | strftime( ( ansible_date_time.epoch | int ) - item.time ) }}'
          with_items: '{{ var_files }}'
    
        - name: find the latest file
          find: paths=/data
            file_type=file
            age=-1m
            age_stamp=mtime
          register: files
    
        - debug:
            msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path if files.files|count > 0 else "cannot find any file" }}'
    
        - name: Copy file, if found
          copy:
            src: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path }}'
            dest: '/tmp/{{ (files.files | sort(attribute="mtime", reverse=true) | first).path | basename }}'
          when: files.files|count > 0
    
        - name: removing files to test the behaviour with no matching files
          file:
            path: '/data/{{ item.name }}'
            state: absent
          with_items: '{{ var_files }}'
    
        - name: find the latest file
          find: paths=/data
            file_type=file
            age=-1m
            age_stamp=mtime
          register: files
    
        - debug:
            msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path if files.files|count > 0 else "cannot find any file" }}'    
    
        - name: Copy file, if found                 
          copy:
            src: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path }}'
            dest: '/tmp/{{ (files.files | sort(attribute="mtime", reverse=true) | first).path | basename }}'
          when: files.files|count > 0
    

    以及该剧本的相应输出

    PLAY [localhost] ********************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************************
    ok: [localhost]
    
    TASK [creating a bunch of matching files] *******************************************************************************************************
    changed: [localhost] => (item={'name': 'a', 'time': 86400})
    changed: [localhost] => (item={'name': 'b', 'time': 30})
    changed: [localhost] => (item={'name': 'c', 'time': 20})
    
    TASK [aging those files] ************************************************************************************************************************
    changed: [localhost] => (item={'name': 'a', 'time': 86400})
    changed: [localhost] => (item={'name': 'b', 'time': 30})
    changed: [localhost] => (item={'name': 'c', 'time': 20})
    
    TASK [find the latest file] *********************************************************************************************************************
    ok: [localhost]
    
    TASK [debug] ************************************************************************************************************************************
    ok: [localhost] => {
        "msg": "/data/c"
    }
    
    TASK [Copy file, if found] **********************************************************************************************************************
    changed: [localhost]
    
    TASK [removing files to test the behaviour with no matching files] ******************************************************************************
    changed: [localhost] => (item={'name': 'a', 'time': 86400})
    changed: [localhost] => (item={'name': 'b', 'time': 30})
    changed: [localhost] => (item={'name': 'c', 'time': 20})
    
    TASK [find the latest file] *********************************************************************************************************************
    ok: [localhost]
    
    TASK [debug] ************************************************************************************************************************************
    ok: [localhost] => {
        "msg": "cannot find any file"
    }
    
    TASK [Copy file, if found] **********************************************************************************************************************
    skipping: [localhost]
    
    PLAY RECAP **************************************************************************************************************************************
    localhost                  : ok=9    changed=4    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
    

    【讨论】:

    • 这看起来很棒。感谢您的详细解释。所以基本上msg 变量会有最新的文件细节,对吧?那么我们也可以将这个最新文件复制到 /tmp 文件夹吗?有没有办法将最新的文件名传递给负责将文件复制到 /tmp 文件夹的 ansible 脚本的下一步?
    • @flash 当然,你现在拥有它
    • 为什么我们在上面的脚本中有10000000w?对于我的用例,我需要在 1 分钟窗口内生成或修改的最新文件,对吗?所以应该是age=-1m?如果我错了,请纠正我
    • @flash 因为,从你的问题来看,这似乎不是你的问题,并且没有必要增加文件创建步骤的复杂性,我只是为了拥有一个完整的例子。但是,如果这确实是您想要的,那么会有更新的答案。
    • 是的,这是有道理的。我想也许你忘了纠正那个。只是想确定一下。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 2012-06-12
    • 1970-01-01
    相关资源
    最近更新 更多