块创建任务的逻辑组。块还提供了一种处理任务错误的方法,类似于许多编程语言中的异常处理。

使用块对任务进行分组

块中的所有任务都会继承在块级别应用的指令。大多数可以在单个任务上应用的内容(循环除外)都可以在块级别应用,因此块使得设置对任务通用的数据或指令变得更加容易。指令不会影响块本身,它只会被块中包含的任务继承。例如,when 语句应用于块内的任务,而不是块本身。

包含命名任务的块示例
 tasks:
   - name: Install, configure, and start Apache
     when: ansible_facts['distribution'] == 'CentOS'
     block:
       - name: Install httpd and memcached
         ansible.builtin.yum:
           name:
           - httpd
           - memcached
           state: present

       - name: Apply the foo config template
         ansible.builtin.template:
           src: templates/src.j2
           dest: /etc/foo.conf

       - name: Start service bar and enable it
         ansible.builtin.service:
           name: bar
           state: started
           enabled: True
     become: true
     become_user: root
     ignore_errors: true

在上面的示例中,将在 Ansible 运行块中的三个任务之前评估 ‘when’ 条件。所有三个任务还继承特权升级指令,以 root 用户身份运行。最后,ignore_errors: true 确保 Ansible 即使某些任务失败,也会继续执行剧本。

注意

块中的所有任务(包括通过 include_role 包含的任务)都会继承在块级别应用的指令。

块的名称自 Ansible 2.3 以来一直可用。我们建议在所有任务中使用名称,无论是在块内还是其他地方,以便在运行剧本时更好地了解正在执行的任务。

使用块处理错误

可以使用带有 rescuealways 部分的块来控制 Ansible 对任务错误的响应方式。

Rescue 块指定在块中先前任务失败时要运行的任务。这种方法类似于许多编程语言中的异常处理。Ansible 仅在任务返回 ‘failed’ 状态后才运行 rescue 块。错误的任务定义和无法访问的主机不会触发 rescue 块。

块错误处理示例
 tasks:
   - name: Handle the error
     block:
       - name: Print a message
         ansible.builtin.debug:
           msg: 'I execute normally'

       - name: Force a failure
         ansible.builtin.command: /bin/false

       - name: Never print this
         ansible.builtin.debug:
           msg: 'I never execute, due to the above task failing, :-('
     rescue:
       - name: Print when errors
         ansible.builtin.debug:
           msg: 'I caught an error, can do stuff here to fix it, :-)'

还可以向块添加 always 部分。always 部分中的任务无论先前块的任务状态如何都会运行。

带有 always 部分的块
 tasks:
   - name: Always do X
     block:
       - name: Print a message
         ansible.builtin.debug:
           msg: 'I execute normally'

       - name: Force a failure
         ansible.builtin.command: /bin/false

       - name: Never print this
         ansible.builtin.debug:
           msg: 'I never execute :-('
     always:
       - name: Always do this
         ansible.builtin.debug:
           msg: "This always executes, :-)"

这些元素一起提供了复杂的错误处理。

带有所有部分的块
 tasks:
   - name: Attempt and graceful roll back demo
     block:
       - name: Print a message
         ansible.builtin.debug:
           msg: 'I execute normally'

       - name: Force a failure
         ansible.builtin.command: /bin/false

       - name: Never print this
         ansible.builtin.debug:
           msg: 'I never execute, due to the above task failing, :-('
     rescue:
       - name: Print when errors
         ansible.builtin.debug:
           msg: 'I caught an error'

       - name: Force a failure in middle of recovery! >:-)
         ansible.builtin.command: /bin/false

       - name: Never print this
         ansible.builtin.debug:
           msg: 'I also never execute :-('
     always:
       - name: Always do this
         ansible.builtin.debug:
           msg: "This always executes"

block 中的任务会正常执行。如果块中的任何任务返回 failed,则 rescue 部分会执行任务来从错误中恢复。always 部分无论 blockrescue 部分的结果如何都会运行。

如果在块中发生错误,并且 rescue 任务成功,Ansible 会恢复原始任务的运行失败状态,并继续运行剧本,就像原始任务成功一样。被恢复的任务被认为是成功的,不会触发 max_fail_percentageany_errors_fatal 配置。但是,Ansible 仍然会在剧本统计信息中报告失败。

可以使用带有 flush_handlers 的块在 rescue 任务中,以确保即使发生错误,所有处理程序也会运行。

在错误处理中运行块处理程序
 tasks:
   - name: Attempt and graceful roll back demo
     block:
       - name: Print a message
         ansible.builtin.debug:
           msg: 'I execute normally'
         changed_when: true
         notify: Run me even after an error

       - name: Force a failure
         ansible.builtin.command: /bin/false
     rescue:
       - name: Make sure all handlers run
         meta: flush_handlers
 handlers:
    - name: Run me even after an error
      ansible.builtin.debug:
        msg: 'This handler runs even on error'

版本 2.1 中的新增功能。

Ansible 为块的 rescue 部分中的任务提供了一些变量。

ansible_failed_task

返回 ‘failed’ 并触发 rescue 的任务。例如,要获取名称,请使用 ansible_failed_task.name

ansible_failed_result

触发 rescue 的失败任务的捕获返回结果。这等效于在 register 关键字中使用此变量。

可以在 rescue 部分中检查这些变量。

在 rescue 部分中使用特殊变量。
 tasks:
   - name: Attempt and graceful roll back demo
     block:
       - name: Do Something
         ansible.builtin.shell: grep $(whoami) /etc/hosts

       - name: Force a failure, if previous one succeeds
         ansible.builtin.command: /bin/false
     rescue:
       - name: All is good if the first task failed
         when: ansible_failed_task.name == 'Do Something'
         ansible.builtin.debug:
           msg: All is good, ignore error as grep could not find 'me' in hosts

       - name: All is good if the second task failed
         when: "'/bin/false' in ansible_failed_result.cmd | d([])"
         ansible.builtin.fail:
           msg: It is still false!!!

注意

ansible-core 2.14 或更高版本中,当嵌套块时,这两个变量都会从内部块传播到外部块的 rescue 部分。

另请参阅

Ansible 剧本

剧本简介

角色

通过角色组织剧本

通讯

有疑问?需要帮助?想分享您的想法?请访问 Ansible 通讯指南。