RHCE8.0讲义:处理任务失败

来自CloudWiki
跳转至: 导航搜索

管理PLAY中的任务错误

背景

Ansible评估各任务的返回代码,从而确定任务是成功还是失败。通常而言,当任务失败时,Ansible将立即在该主机上中止play的其余部分并且跳过所有后续任务。

但有些时候,您可能希望即使在任务失败时也继续执行play。例如,您或许预期特定任务有可能 会失败,并且希望通过有条件地运行某项其他任务来恢复。有多种Ansible功能可用于管理任务错误。

忽略任务失败

默认情况下,任务失败时play会中止。不过,可以通过忽略失败的任务来覆盖此行为。您可以在任 务中使用ignore_errors关键字来实现此目的。

下列代码片段演示了如何在任务中使用ignore_errors,以便在任务失败时也继续在主机上执行 playbooko例如,如果notapkg软件包不存在,则yum模块将失败,但若将ignore_errors设 为yes,则执行将继续。

---
- name: my_first_play
  hosts: slave
  tasks:
    - name: Latest version of notapkg is installed
      yum:
        name: notapkg
        state: latest
      ignore_errors: yes

试验:加上和去掉ignore_errors: yes关键字 看看输出有什么不同。

任务失败后强制执行处理程序

通常而言,如果任务失败并且play在该主机上中止,则收到play中早前任务通知的处理程序将不 会运行。如果您在play中设置force_handlers: yes关键字,则即使play因为后续任务失败而 中止也会调用被通知的处理程序。

下列代码片段演示了如何在play中使用force_handlers关键字,以便在任务失败时也强制执行 相应的处理程序:

---
- hosts: all
  force_handlers: yes
  tasks:
    - name: a task which always notifies its handler
      command: /bin/true
      notify: restart the database
    - name: a task which fails because the package doesn1t exist
      yum:
        name: notapkg
        state: latest
  handlers:
    - name: restart the database
      service:
        name: mariadb
        state: restarted


试验:加上和去掉force_handlers: yes关键字 看看输出有什么不同。

注意

请记住,处理程序会在任务报告changed结果时获得通知,而在任务报告ok或 failed结果时不会获得通知。

指定任务失败条件

您可以在任务中使用failed_when关键字来指定表示任务已失败的条件。这通常与命令模块搭配 使用,这些模块可能成功执行了某一命令,但命令的输出可能指示了失败。

例如,您可以运行输出错误消息的脚本,并使用该消息定义任务的失败状态。下列代码片段演示了 如何在任务中使用failed_when关键字:

tasks:
  - name: Run user creation script
    shell: /usr/local/bin/create_users.sh
    register: command_result
    failed_when: "1 Password missing' in command_result.stdout"

fail模块也可用于强制任务失败。上面的场景也可以编写为两个任务:

tasks:
  - name: Run user creation script
    shell: /usr/local/bin/create_users.sh
    register: command_result
    ignore_errors: yes
  - name: Report script failure
    fail:
      msg: "The password is missing in the output"
    when: "'Password missing' in command_result.stdout"

您可以使用fail模块为任务提供明确的失败消息。此方法还支持延迟失败,允许您运行中间任务 以完成或回滚其他更改。

指定何时任务报告“Changed”结果

当任务对托管主机进行了更改时,会报告changed状态并通知处理程序。如果任务不需要进行更 改,则会报告ok并且不通知处理程序。

changed_when关键字可用于控制任务在何时报告它已进行了更改。例如,下一个示例中的 shell模块将用于获取供后续任务使用的Kerberos凭据。它通常会在运行时始终报告changed。 为抑制这种更改,应设置changed_when: false,以便它仅报告ok或failed。

- name: get Kerberos credentials as "admin"
  shell: echo "({ krb_admin_pass }}" | kinit -f admin 
  changed_when: false

以下示例使用shell模块,根据通过已注册变量收集的模块的输出来报告changed:

tasks:
  - shell:
    cmd: /usr/local/bin/upgrade-database
    register: command_result
    changed_when: "'Success' in command_result.stdout"
    notify:
      - restart_database

handlers:
  - name: restart_database
    service:
      name: mariadb
      state: restarted

Ansible块和错误处理

在playbook中,块是对任务进行逻辑分组的子句,可用于控制任务的执行方式。例如,任务块可以 含有when关键字,以将某一条件应用到多个任务:

- name: block example
  hosts: all
  tasks:
    - name: installing and configuring Yum versionlock plugin
      block:
        - name: package needed by yum
          yum:
            name: yum-plugin-versionlock
            state: present
        - name: lock version of tzdata
          lineinfile:
            dest: /etc/yum/pluginconf.d/versionlock.list
            line: tzdata-2016j-1
            state: present
      when: ansible_distribution == "RedHat"

通过块,也可结合rescue和always语句来处理错误。如果块中的任何任务失败,则执行其 rescue块中的任务来进行恢复。在block子句中的任务以及rescue子句中的任务(如果出现故 障)运行之后,always子句中的任务运行。

总结:

  • block:定义要运行的主要任务。
  • rescue:定义要在block子句中定义的任务失败时运行的任务。
  • always:定义始终都独立运行的任务,不论block和rescue子句中定义的任务是成功还是失 败。

以下示例演示了如何在playbook中实施块。即使block子句中定义的任务失败,rescue和 always子句中定义的律务也会执行。

tasks:
  - name: Upgrade DB
    block:
      - name: upgrade the database
        shell:
          cmd: /usr/local/lib/upgrade-database
    rescue:
      - name: revert the database upgrade
        shell:
          cmd: /usr/local/lib/revert-database
    always:
      - name: always restart the database
        service:
          name: mariadb
          state: restarted

block中的when条件也会应用到其rescue和always子句(若存在)。

参考文献

LjJ Playbook 中的错误处理 — Ansible 文档 https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html

错误处理—块— Ansible文档 https://docs.ansible.eom/ansible/latest/user_guide/playbooks_blocks.html#eiT" handling