如何在 Ansible Playbook 中使用处理程序

处理程序 就像 ansible 中的常规任务一样,只有在收到通知时才会运行。 处理程序是一个非常有用且重要的概念 Ansible.

运行处理程序任务涉及两个指令。

  • 通知指令 这会将触发信号发送到要运行的任务。
  • 处理程序指令 任务被分组在哪个之下。

让我们谈谈一个实际的用例。 假设您想编写一个 SSH 加固手册,您将在其中对 ssh 配置文件进行一些更改。

如您所知,任何配置更改都需要重新启动服务才能使更改生效。 这是处理程序非常有效的地方。

一旦任务在 sshd 配置文件中进行了更改,我们可以向将重新启动的任务发送信号 sshd 服务。

内容

  1. Ansible 处理程序关键点
  2. 调用多个任务
  3. 执行顺序
  4. 只运行一次
  5. 重复任务
  6. 处理任务失败
    1. 1. 强制处理程序
    2. 2.忽略错误
  7. 冲洗处理程序
  8. 使用“Listen”运行处理程序任务
  9. 结论

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
元 - Ansible 文档元 – Ansible 文档

冲洗处理程序 将运行已将信号发送到通知指令的所有任务。

- 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 管理