如何编写仅在任务文件中的任何先前其他任务已更改时运行的 Ansible 角色任务?

How to write an Ansible role task that only runs when any of the previous other tasks in the task file have been changed?

我正在担任一个角色,当且仅当 any 之前任务中的 any该任务文件已更改。

比如我有:

- name: install package
  apt: name=mypackage state=latest

- name: modify a file
  lineinfile: do stuff

- name: modify a second file
  lineinfile: other stuff

- name: restart if anything changed
  service: name=mypackage state=restarted

...而且我只想在安装了更新或更改了任何配置文件后才重新启动服务。

我该怎么做?

此处的最佳做法是使用 handlers

在您的角色中创建一个文件handlers/main.yml,内容为:

- name: restart mypackage
  service: name=mypackage state=restarted

然后从所有任务中通知此处理程序。仅当任务报告更改状态(=黄色输出)时才会通知处理程序

- name: install package
  apt: name=mypackage state=latest
  notify: restart mypackage

- name: modify a file
  lineinfile: do stuff
  notify: restart mypackage

- name: modify a second file
  lineinfile: other stuff
  notify: restart mypackage

处理程序将在您的游戏结束时执行。如果您有其他角色涉及依赖于重新启动的 mypackage 服务,您可能希望在角色结束时刷新所有处理程序:

- meta: flush_handlers

另外看看 force_handlers 设置。如果在您的 mypackge 角色之后处理的任何其他角色发生错误,则不会触发处理程序。在您的 ansible.cfg 中设置 force_handlers=True 以仍然强制您的处理程序在出错后执行。这是一个非常重要的主题,因为当您下次 运行 您的剧本时,文件将不会更改,因此处理程序不会收到通知,因此您的服务永远不会重新启动。


您也可以在没有处理程序的情况下执行此操作,但这非常难看。您需要注册每个任务的输出,以便稍后检查应用于重启任务的条件中的状态。

- name: install package
  apt: name=mypackage state=latest
  register: mypackage_1

- name: modify a file
  lineinfile: do stuff
  register: mypackage_2

- name: modify a second file
  lineinfile: other stuff
  register: mypackage_3

- name: restart if anything changed
  service: name=mypackage state=restarted
  when: mypackage_1 is changed or mypackage_2 is changed or mypackage_3 is changed

可以使用mypackage_1 |更改为 ansible 2.9

另请参阅 的答案。