我想在整个剧本中只运行一次处理程序。
我尝试在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
以下是处理程序/ 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
如何让剧本只对整个剧本执行一次处理程序?
答案 0 :(得分:10)
答案
标题中问题的字面答案是:否。
Playbook是一个播放列表。 Playbook没有命名空间,没有变量,没有状态。所有配置,逻辑和任务都在播放中定义。
处理程序是一个具有不同调用计划的任务(不是顺序的,而是有条件的,一旦在游戏结束时,或由meta: flush_handlers
任务触发)。
处理程序属于一个游戏,而不是一个剧本,并且无法在游戏之外触发它(即在剧本的末尾)。
<强>解决方案强>
可以在不参考处理程序的情况下解决问题。
您可以使用group_by
module根据每个游戏底部的任务结果创建一个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
答案 1 :(得分:2)
使用处理程序将主机添加到内存清单中。然后添加play
以仅对这些主机运行重新启动服务。
参见以下示例:
如果任务已更改,它将通知mark to restart
设置事实,即主机需要重新启动服务。
第二个处理程序add host
非常特殊,因为add_host
任务即使在处理程序中也只对整个游戏运行一次,另请参见documentation。但是,如果得到通知,它将在处理程序命令中隐含的标记完成后运行。
处理程序会在运行任务的主机上循环,并检查是否需要重新启动主机服务;如果需要,请添加到特殊的hosts_to_restart
组。
由于事实在游戏中始终存在,因此请通知第三台处理程序clear mark
以了解受影响的主机。
通过移动处理程序隐藏的许多行可以分隔文件并包含它们。
库存文件
10.1.1.[1:10]
[primary]
10.1.1.1
10.1.1.5
test.yml
---
- hosts: all
gather_facts: no
tasks:
- name: Random change to notify trigger
debug: msg="test"
changed_when: "1|random == 1"
notify:
- mark to restart
- add host
- clear mark
handlers:
- name: mark to restart
set_fact: restart_service=true
- name: add host
add_host:
name: "{{item}}"
groups: "hosts_to_restart"
when: hostvars[item].restart_service is defined and hostvars[item].restart_service
with_items: "{{ansible_play_batch}}"
- name: clear mark
set_fact: restart_service=false
- hosts: primary
gather_facts: no
tasks:
- name: Change to notify trigger
debug: msg="test"
changed_when: true
notify:
- mark to restart
- add host
- clear mark
handlers:
- name: mark to restart
set_fact: restart_service=true
- name: add host
add_host:
name: "{{item}}"
groups: "hosts_to_restart"
when: hostvars[item].restart_service is defined and hostvars[item].restart_service
with_items: "{{ansible_play_batch}}"
- name: clear mark
set_fact: restart_service=false
- hosts: hosts_to_restart
gather_facts: no
tasks:
- name: Restart service
debug: msg="Service restarted"
changed_when: true
答案 2 :(得分:0)
我不清楚你的处理程序应该做什么。无论如何,至于https://www.dll-files.com/,处理程序
在游戏中的每个任务块结束时触发, 并且即使被多个不同的通知也只会触发一次 任务 [...]从Ansible 2.2开始,处理程序也可以“监听”通用主题,任务可以按如下方式通知这些主题:
因此,每个任务块都会通知/执行一次处理程序。 可能是你的目标只是在“所有”目标主机之后保留处理程序,但它似乎并不是处理程序的干净利用。
答案 3 :(得分:0)
在binary crossentropy
中触发的处理程序将在所有其他操作之后运行。并且可以将处理程序设置为post_tasks
。