处理程序 就像 ansible 中的常规任务一样,只有在收到通知时才会运行。 处理程序是一个非常有用且重要的概念 Ansible.
运行处理程序任务涉及两个指令。
- 通知指令 这会将触发信号发送到要运行的任务。
- 处理程序指令 任务被分组在哪个之下。
让我们谈谈一个实际的用例。 假设您想编写一个 SSH 加固手册,您将在其中对 ssh 配置文件进行一些更改。
如您所知,任何配置更改都需要重新启动服务才能使更改生效。 这是处理程序非常有效的地方。
一旦任务在 sshd 配置文件中进行了更改,我们可以向将重新启动的任务发送信号 sshd
服务。
内容
Ansible 处理程序关键点
在深入动手部分之前,让我们了解一些关于处理程序的要点。
- 处理程序任务只会在父任务进行更改时运行(changed=true)。
- 处理程序任务只会在每次播放结束时运行,但我们可以选择在任何我们想要的地方运行它。
- 无论您在单个主机上调用多少次相同的处理程序任务,处理程序任务都只会运行一次。
- 任务名称应该是唯一的。 如果两个任务具有相同的名称,则只有第一个任务会运行。
- 任务将按照它们在 handler 指令下定义的顺序执行,而不是按照 notify 指令调用的顺序。
句法
要定义处理程序任务, 通知 和 处理程序 应该使用指令。 Notify 指令将信号发送到处理程序任务执行。
以下是示例剧本。 我在处理程序指令下定义了两个任务。 要运行这些任务,使用通知指令并将任务名称作为值传递。
- name: Handlers testing hosts: ubuntu.anslab.com gather_facts: false tasks: - name: Get the hostname shell: hostname -s register: hostname notify: print hostname handlers: - name: print hostname debug: var: hostname.stdout - name: print IP debug: var: IP.stdout
下面是剧本的输出。 即使我在处理程序中有两个任务,也只有一个任务运行,它通过 notify 指令调用。
调用多个任务
在单个通知指令下,您可以调用多个处理程序任务。 在 YAML
列表格式。
- name: Get the hostname shell: hostname -s register: hostname notify: - print hostname - print IP
Python 列表表示法也可用于调用多个处理程序任务。
- name: Get the hostname shell: hostname -s register: hostname notify: ["print hostname", "print IP"]
执行顺序
处理程序任务将仅在播放结束时运行,即使在任何任务之前调用它也是如此。
- name: Handlers testing hosts: ubuntu.anslab.com gather_facts: false tasks: - name: Get the hostname shell: hostname -s register: hostname notify: print hostname - name: Get IP address of the hostname shell: hostname -I register: IP notify: print IP handlers: - name: print hostname debug: var: hostname.stdout - name: print IP debug: var: IP.stdout
看看上面的剧本。 第一个任务(获取主机名)正在调用处理程序任务(打印主机名)。 第二个任务是调用第二个处理程序任务(打印 IP)。
当我运行剧本时,两个任务将首先执行并将信号发送到处理程序,一旦所有任务完成,处理程序任务就会运行。
小心: 不管处理程序任务如何被调用,它都会按照处理程序指令中定义的顺序执行。
只运行一次
您可以多次调用同一个处理程序任务,但处理程序任务只会运行一次。
我正在运行我在上一节中使用的相同剧本,但修改了 notify 指令以调用相同的处理程序任务(print hostname
)。
- name: Handlers testing hosts: ubuntu.anslab.com gather_facts: false tasks: - name: Get the hostname shell: hostname -s register: hostname notify: print hostname - name: Get IP address of the hostname shell: hostname -I register: IP notify: print hostname handlers: - name: print hostname debug: var: hostname.stdout - name: print IP debug: var: IP.stdout
从下面的输出可以看出,打印主机名处理程序任务只运行了一次。
重复任务
正如我在介绍部分中所说,您应该为任务提供描述性和唯一的名称。 如果定义了两个或多个同名任务,则只有 ansible 读取的第一个任务会运行,而忽略所有其他同名任务。
如果您查看以下任务,两个任务名称是相同的。 现在,当我运行 playbook 时,ansible 将运行第一个处理程序任务并打印 IP。
handlers: - name: print hostname debug: var: IP.stdout - name: print hostname debug: var: hostname.stdout
处理任务失败
在 ansible 中,如果一个任务失败,后续任务将不会运行。 处理程序如何处理故障是,如果任何任务在特定主机中失败,则即使失败的任务不是父任务(通知指令),处理程序任务也不会为该主机运行。
如果你可以看看下面的剧本,有两个任务使用了 shell 模块。 第一个任务使用 /bin/true
它会一直运行良好。 此任务调用处理程序任务 (run_now),它只是将消息打印到标准输出。 第二个任务通过使用设置为失败 /bin/false
.
- name: Testing handler hosts: ubuntu.anslab.com gather_facts: false tasks: - name: set a task to success shell: /bin/true notify: run_now - name: set a task to fail shell: /bin/false handlers: - name: run_now debug: msg="I am called from [ task 1 ]"
如果您可以看到下图,则第一个任务的输出运行良好,并向处理程序任务发送信号以运行,但同一主机中的下一个任务失败,因此处理程序任务未运行。
让我们看看如何使用不同的选项来处理任务失败。
1. 强制处理程序
你可以设置属性 force_handlers: true
在 playbook 中,即使您有任务失败,它也会运行处理程序任务。
您也可以在不同的区域设置此参数。
- 剧本⇒
force_handlers: true
- ansible.cfg 文件⇒
force_handlers = true
- 命令行参数⇒
--force-handlers
2.忽略错误
也可以设置属性 ignore_errors: true
这将忽略失败的任务并执行处理程序任务。
冲洗处理程序
到这个时候,您应该已经了解处理程序任务只会在播放结束时运行。 但是有一种方法可以让它在我们希望的任何时候运行。 这可以通过元模块来实现 冲洗处理程序 命令。
$ ansible-doc meta
冲洗处理程序 将运行已将信号发送到通知指令的所有任务。
- name: Testing handler hosts: ubuntu.anslab.com gather_facts: false tasks: - name: set a task to success shell: /bin/true notify: run_now - name: Run handler now meta: flush_handlers - name: set a task to fail shell: /bin/false handlers: - name: run_now debug: msg="I am called from [ task 1 ]"
从上面的输出可以看出,处理程序任务作为游戏中的第二个任务运行。
使用“Listen”运行处理程序任务
到目前为止,我们已经使用任务名称触发了所有处理程序任务。 使用 ”listen
“,您可以将多个任务分组并通过 notify 语句运行所有任务。这是使用处理程序时标签的一个很好的替代选项。
如果你看到下面的剧本,我已经设置了 听 至 “所有任务” 并通过 通知 指示。
- name: Testing handler hosts: ubuntu.anslab.com gather_facts: false tasks: - name: set a task to success shell: /bin/true notify: "all task" handlers: - name: handler task 1 debug: msg: This is handler task 1 listen: "all task" - name: handler task 2 debug: msg: This is handler task 2 listen: "all task" - name: handler task 3 debug: msg: This is handler task 3 listen: "all task"
结论
在本文中,我们了解了处理程序是什么以及如何使用 ansible playbook 中的通知和处理程序指令来实现不同的目标。
我们还看到了如何使用两种不同的选项来处理任务失败。 最后,我们以如何使用 listen 指令触发多个任务来结束本文。
资源:
- 处理程序:对更改运行操作
AnsibleAnsible 命令Ansible PlaybooksAnsible 系列Ansible 教程DevOpsHandlersIT 自动化LinuxLinux 管理