仅当有更新的文件时才运行命令的 Ansible 剧本

仅当有更新的文件时才运行命令的 Ansible 剧本

由于某些旧设置不允许我更改,我们的一些 DNS 区域是基于文件而不是基于数据库,并且它们通过 rsync 从主服务器传输到辅助服务器。

最近,我一直在学习通过 ansible playbook 自动执行各种维护任务,以下 playbook 让我可以自动重新加载所有身份验证服务器:

---
- hosts: auth
  name: Reload PDNS auth servers
  become: no

  tasks:
   - name: Check if PDNS is running
     service:
       name: pdns
       state: started
   - name: Execute reload command.
     command: /usr/bin/pdns_control reload

这工作得很好,考虑到重新加载命令几乎不会增加服务器上的负载,它算作“足够好”,但我的轻度强迫症变得抽搐,我会真的希望能够告诉它“仅当有任何文件/etc/powerdns/bindbackend/zones/比指定的时间戳文件更新时才执行重新加载。”

从我在文档中看到的内容来看,我需要查看when和/或find子句 - 运行find并仅在结果数大于零时执行重新加载序列 - 但我不确定如何制定“任何”/tmp/timestamp在 ansible playbook 语法中早于 ' 的文件。

有什么指点吗?

答案1

我想这就是你要找的

  - name: Find timestamp
    find:
      paths: /tmp
      patterns: timestamp
    register: my_timestamp

  - name: Timestamp not found. End of host.
    block:
      - debug:
          msg: /tmp/timestamp not found. End of host.
      - meta: end_host
    when: my_timestamp.matched == 0

  - name: Find all zone files
    find:
      paths: "{{ zones_dir }}"
    register: my_zones

  - name: Find zone files newer than timestamp
    set_fact:
      my_zones_newer: "{{ my_zones.files|json_query(query)
                          map('basename')|
                          list }}"
    vars:
      query: "[?mtime > to_number('{{ my_timestamp.files.0.mtime }}')].path"

  - block:
      - name: "Reload {{ my_zones_newer|join(',') }}"
        command: /usr/bin/pdns_control reload
      - name: Touch timestamp
        file:
          state: touch
          path: /tmp/timestamp
    when: my_zones_newer|length > 0


“查找所有区域文件”和“触摸时间戳”之间的关键部分

如果在此关键部分写入区域文件,则不会触发重新加载。要解决此问题,请将mtime文件设置/tmp/timestamp为找到的最新区域文件的值,以避免潜在的危险。更改块

  - block:
      - name: "Reload {{ my_zones_newer|join(',') }}"
        command: /usr/bin/pdns_control reload
      - set_fact:
          my_mtime_max: "{{ my_zones.files|json_query('[].mtime')|max }}"
      - file:
          state: touch
          modification_time: "{{ '%Y%m%d%H%M.%S'|
                                 strftime(my_mtime_max|
                                          float|
                                          round(precision=0, method='ceil')|
                                          int) }}"
          path: /tmp/timestamp
    when: my_zones_newer|length > 0

看来粒度是修改时间格式是第二个。看时间.strftime。因此,my_mtime_max必须对变量进行四舍五入,method='ceil'从而将危险留在秒的四舍五入部分中。


将 mtime 存储在时间戳中

健壮的解决方案是存储mtime在文件中timestamp。例如,

  - name: Read modification time from /tmp/timestamp (default=0)
    set_fact:
      my_mtime_max: "{{ lookup('pipe', my_command) }}"
    vars:
      my_command: sh -c '[ -e /tmp/timestamp ] && cat /tmp/timestamp || echo 0'

  - name: Find all zone files
    find:
      paths: "{{ zones_dir }}"
    register: my_zones

  - name: Find zone files newer than timestamp
    set_fact:
      my_zones_newer: "{{ my_zones.files|json_query(query)|
                          map('basename')|
                          list }}"
    vars:
      query: "[?mtime > to_number('{{ my_mtime_max }}')].path"

  - block:
      - name: "Reload {{ my_zones_newer|join(',') }}"
        command: /usr/bin/pdns_control reload
      - name: Set mtime of newest zone file to my_mtime_max
        set_fact:
          my_mtime_max: "{{ my_zones.files|json_query('[].mtime')|max }}"
      - name: Store my_mtime_max in /tmp/timestamp
        template:
          src: timestamp.j2
          dest: /tmp/timestamp
    when: my_zones_newer|length > 0
shell> cat timestamp.j2 
{{ my_mtime_max }}

相关内容