我想在整个剧本中只运行一次处理程序.
我尝试在playbook文件中使用下面的include语句,但这导致处理程序多次运行,每次播放一次:
- name: Configure common config hosts: all become: true vars: OE: "{{ ansible_hostname[5] }}" roles: - { role: common } handlers: - include: handlers/main.yml - name: Configure metadata config hosts: metadata become: true vars: OE: "{{ ansible_hostname[5] }}" roles: - { role: metadata } handlers: - include: handlers/main.yml
这是handlers/main.yml的内容:
- name: restart autofs service: name: autofs.service state: restarted
以下是通知处理程序的任务之一的示例:
- name: Configure automount - /opt/local/xxx in /etc/auto.direct lineinfile: dest: /etc/auto.direct regexp: "^/opt/local/xxx" line: "/opt/local/xxx -acdirmin=0,acdirmax=0,rdirplus,rw,hard,intr,bg,retry=2 nfs_server:/vol/xxx" notify: restart autofs
我怎样才能让剧本只为整个剧本执行一次处理程序?
答案
标题中问题的字面答案是:不.
Playbook是一个剧本列表.Playbook没有命名空间,没有变量,没有状态.所有配置,逻辑和任务都在播放中定义.
处理程序是一个具有不同调用计划的任务(不是顺序的,而是有条件的,一旦在游戏结束时,或由meta: flush_handlers
任务触发).
处理程序属于一个游戏,而不是一个剧本,并且没有办法在游戏之外(即在剧本的末尾)触发它.
解
无需参考处理程序即可解决问题.
您可以使用group_by
模块根据每个游戏底部的任务结果创建一个ad-hoc组.
然后,您可以在剧本的末尾定义单独的播放,在属于上述ad-hoc群组的目标上重新启动服务.
请参阅以下存根以获取该想法:
- hosts: all roles: # roles declaration tasks: - # an example task modifying Nginx configuration register: nginx_configuration # ... other tasks ... - name: the last task in the play group_by: key: hosts_to_restart_{{ 'nginx' if nginx_configuration is changed else '' }} # ... other plays ... - hosts: hosts_to_restart_nginx gather_facts: no tasks: - service: name: nginx state: restarted