handlers:对更改运行操作
有时,您希望仅在机器上发生更改时才运行任务。例如,如果任务更新了该服务的配置,您可能希望重新启动该服务,但如果配置未更改,则不需要。Ansible 使用处理程序来解决这个用例。处理程序是仅在收到通知时运行的任务。每个处理程序都应该有一个全局唯一的名称。
1、handlers示例
这个playbook,verify-apache.yml,包含一个带有处理程序的单一剧本。
---- name: Verify apache installation
hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
name: Ensure apache is at the latest version
ansible.builtin.yum:name: httpd state: latest
name: Write the apache config file
ansible.builtin.template:src: /srv/httpd.j2 dest: /etc/httpd.conf
notify:
- Restart apache
name: Ensure apache is running
ansible.builtin.service:name: httpd state: started
handlers:
- name: Restart apache
ansible.builtin.service:
name: httpd
state: restarted
在此示例剧本中,第二个任务通知处理程序。
并且单个任务(notify)可以通知多个处理程序(handlers)。
name: Template configuration file
ansible.builtin.template:
src: template.j2
dest: /etc/foo.conf
notify:- Restart memcached
- Restart apache
handlers:
name: Restart memcached
ansible.builtin.service:name: memcached state: restarted
name: Restart apache
ansible.builtin.service:name: apache state: restarted
2、控制handlers何时运行
默认情况下,handlers在特定播放中的所有任务完成后运行。这种方法很有效,因为处理程序只运行一次,而不管有多少任务通知它。例如,如果多个任务更新配置文件并通知处理程序重新启动 Apache,Ansible 只会反弹一次 Apache 以避免不必要的重新启动。
如果您需要在播放结束之前运行处理程序,请添加一个任务以使用执行 Ansible 操作的元模块刷新它们。
tasks:
- name: Some tasks go here
ansible.builtin.shell: ... - name: Flush handlers
meta: flush_handlers - name: Some other tasks
ansible.builtin.shell: ...
该任务触发在播放中当时已通知的任何处理程序。meta: flush_handlers
3、使用带有handlers的变量
您可能希望您的 Ansible 处理程序(handlers)使用变量。例如,如果服务的名称因分布而略有不同,您希望输出显示每台目标机器的重新启动服务的确切名称。避免将变量放在处理程序的名称中。由于处理程序名称在早期是模板化的,因此 Ansible 可能没有可用于处理程序名称的值,如下所示:
handlers:# This handler name may cause your play to fail!- name: Restart "{{ web_service_name }}"
如果处理程序名称中使用的变量不可用,则整个播放失败。更改该变量 mid-play不会导致新创建的处理程序。
相反,将变量放在处理程序的任务参数中。您可以include_vars像这样加载值:
tasks:
- name: Set host variables based on distribution
include_vars: "{{ ansible_facts.distribution }}.yml"
handlers:
name: Restart web service
ansible.builtin.service:name: "{{ web_service_name | default('httpd') }}" state: restarted
处理程序还可以“监听”通用主题,任务可以通知这些主题,如下所示:
handlers:
name: Restart memcached
ansible.builtin.service:name: memcached state: restarted
listen: "restart web services"
name: Restart apache
ansible.builtin.service:name: apache state: restarted
listen: "restart web services"
tasks:
- name: Restart everything
ansible.builtin.command: echo "this task will restart the web services"
notify: "restart web services"
这种用法使得触发多个处理程序变得更加容易。它还将处理程序与其名称分离,从而更容易在剧本和角色之间共享处理程序(尤其是在使用来自 Galaxy 等共享源的第 3 方角色时)。
笔记
处理程序总是按照它们定义的顺序运行,而不是按照通知语句中列出的顺序。使用listen的处理程序也是如此。
处理程序名称和侦听主题位于全局命名空间中。
处理程序名称是可模板化的,而监听主题则不是。
使用唯一的处理程序名称。如果您触发多个具有相同名称的处理程序,则第一个处理程序将被覆盖。只有定义的最后一个会运行。
您可以通知静态包含中定义的处理程序。
您无法通知动态包含中定义的处理程序。
处理程序不能运行 import_role 或 include_role。
在角色中使用处理程序时,请注意:
pre_tasks在、tasks和部分中通知的处理程序post_tasks会在通知它们的部分末尾自动刷新。
在节内通知的处理程序会在roles节结束时自动刷新tasks,但在任何tasks处理程序之前。
处理程序是作用域的,因此可以在定义它们的角色之外使用。