RHCE8.0实训:处理任务失败

来自CloudWiki
跳转至: 导航搜索

实训目的

  • 在执行playbook期间忽略失败的命令。
  • 强制执行处理程序。
  • 覆盖造成任务失败的条目。
  • 覆盖任务的changed状态。
  • 在 playbook 中实施 block、rescue 和 always

实训步骤

[student@workstation ~]$ cd ~/control-errors [student@workstation control-errors]$

清单文件

[root@servera control-errors]# cat /etc/ansible/hosts

[database_dev]
servera.lab.example.com
[database_prod]
serverb.lab.example.com

运行初始play

创建playbook.yml playbook,它将含有一个包含两个任务的play。编写第一个任务,有意包含一个将导致失败的错误。


---
  - name: Task Failure Exercise
    hosts: database_dev
    vars:
      web_package: http
      db_package: mariadb-server
      db_service: mariadb
    tasks:
      - name: Install {{ web_package }} package
        yum:
          name: "{{ web_package }}"
          state: present
      - name: Install {{ db_package }} package
        yum:
          name: "{{ db_package }}"
          state: present   

[root@servera control-errors]# ansible-playbook playbook.yml --syntax-check

playbook: playbook.yml

[root@servera control-errors]# ansible-playbook playbook.yml

PLAY [Task Failure Exercise] *************************************************************************************

TASK [Gathering Facts] *******************************************************************************************
ok: [servera.lab.example.com]

TASK [Install http package] **************************************************************************************
fatal: [servera.lab.example.com]: FAILED! => {"changed": false, "msg": "No package matching 'http' found available, installed or updated", "rc": 126, "results": ["No package matching 'http' found available, installed or updated"]}

PLAY RECAP *******************************************************************************************************
servera.lab.example.com    : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0


任务将失败,因为不存在名为http的现有软件包。由于第一个任务失败,因此未运行第二 个任务。

添加ignore_errors关键字

通过添加ignore_errors关键字更新第一个任务,以忽略任何错误。这些任务应当如下所 示:

---
  - name: Task Failure Exercise
    hosts: database_dev
    vars:
      web_package: http
      db_package: mariadb-server
      db_service: mariadb
    tasks:
      - name: Install {{ web_package }} package
        yum:
          name: "{{ web_package }}"
          state: present
        ignore_errors: yes
      - name: Install {{ db_package }} package
        yum:
          name: "{{ db_package }}"
          state: present
~

再次运行playbook,并观察play的输出。

[root@servera control-errors]# ansible-playbook playbook.yml --syntax-check

playbook: playbook.yml

[root@servera control-errors]# ansible-playbook playbook.yml

PLAY [Task Failure Exercise] *************************************************************************************

TASK [Gathering Facts] *******************************************************************************************
ok: [servera.lab.example.com]

TASK [Install http package] **************************************************************************************
fatal: [servera.lab.example.com]: FAILED! => {"changed": false, "msg": "No package matching 'http' found available, installed or updated", "rc": 126, "results": ["No package matching 'http' found available, installed or updated"]}
...ignoring

TASK [Install mariadb-server package] ****************************************************************************
ok: [servera.lab.example.com]

PLAY RECAP *******************************************************************************************************
servera.lab.example.com    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1


尽管第一个任务失败,但Ansible仍然执行了第二个任务。

设置block关键字

在这一步中,您将设置block关键字,以便您可以试验它的运作方式。

更新playbook,将第一个任务嵌套在block子句中。删除设置ignore_errors: yes的行。这个块应当如下所示:

---
  - name: Task Failure Exercise
    hosts: database_dev
    vars:
      web_package: httpd
      db_package: mariadb-server
      db_service: mariadb
    tasks:
      - name: Attempt to set up a webserver
        block:
          - name: Install {{ web_package }} package
            yum:
              name: "{{ web_package }}"
              state: present
        rescue:
          - name: Install {{ db_package }} package
            yum:
              name: "{{ db_package }}"
              state: present
        always:
          - name: Start {{ db_service }} service
            service:
              name: "{{ db_service }}"
              state: started

运行playbook。块中确保已安装web_package的任务失败,这将导致rescue块中的 任务运行。然后,always块中的任务将运行。

编辑playbook,更正web_package变量的值,使其显示为httpd。这样,下次运行 该playbook时块中的任务会成功。

[root@servera control-errors]# ansible-playbook playbook.yml

PLAY [Task Failure Exercise] *************************************************************************************

TASK [Gathering Facts] *******************************************************************************************
ok: [servera.lab.example.com]

TASK [Install httpd package] *************************************************************************************
ok: [servera.lab.example.com]

TASK [Start mariadb service] *************************************************************************************
ok: [servera.lab.example.com]

PLAY RECAP *******************************************************************************************************
servera.lab.example.com    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

</nowiki>

再次运行该playbooko这一次,块中的任务不会失败。这将导致rescue部分中的任务 被忽略。always中的任务仍然会运行


更改change条件

编辑playbook,在play的开头、block的前面添加两个任务。第一个任务使用 command模块运行date命令,并将结果注册在command_result变量中。第二个任 务使用debug模块显示第一个任务的命令的标准输出。

      - name: Check local time
        command: date
        register: command_result
      - name: Print local time
        debug:
          var: command_result.stdout

运行playbooko您应当会看到运行command模块的第一个任务报告changed,尽管它 没有更改远程系统;它只是收集了有关时间的信息。这是因为command模块无法区分 收集数据的命令和更改状态的命令。

[root@servera control-errors]# ansible-playbook playbook-3.yml

PLAY [Task Failure Exercise] ***************************************************

TASK [Gathering Facts] *********************************************************
ok: [servera.lab.example.com]

TASK [Check local time] ********************************************************
changed: [servera.lab.example.com]

TASK [Print local time] ********************************************************
ok: [servera.lab.example.com] => {
    "command_result.stdout": "Wed Feb 17 19:07:21 CST 2021"
}

TASK [Install httpd package] ***************************************************
ok: [servera.lab.example.com]

TASK [Start mariadb service] ***************************************************
ok: [servera.lab.example.com]

PLAY RECAP *********************************************************************
servera.lab.example.com    : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

此command任务没有更改托管主机,所以不应每次运行时都报告changed 由于您知道 该任务绝不会更改托管主机,因此在任务中添加changed_when: false行以抑制更 改

vi playbook-3.yml

---
  - name: Task Failure Exercise
    hosts: database_dev
    vars:
      web_package: httpd
      db_package: mariadb-server
      db_service: mariadb
    tasks:
      - name: Check local time
        command: date
        register: command_result
        changed_when: false
      - name: Print local time
        debug:
          var: command_result.stdout
      - name: Attempt to set up a webserver
        block:
          - name: Install {{ web_package }} package
            yum:
              name: "{{ web_package }}"
              state: present
        rescue:
          - name: Install {{ db_package }} package
            yum:
              name: "{{ db_package }}"
              state: present
        always:
          - name: Start {{ db_service }} service
            service:
              name: "{{ db_service }}"
              state: started

[root@servera control-errors]# ansible-playbook playbook-3.yml


PLAY [Task Failure Exercise] ***************************************************

TASK [Gathering Facts] *********************************************************
ok: [servera.lab.example.com]

TASK [Check local time] ********************************************************
ok: [servera.lab.example.com]

TASK [Print local time] ********************************************************
ok: [servera.lab.example.com] => {
    "command_result.stdout": "Wed Feb 17 19:06:07 CST 2021"
}

TASK [Install httpd package] ***************************************************
ok: [servera.lab.example.com]

TASK [Start mariadb service] ***************************************************
ok: [servera.lab.example.com]

PLAY RECAP *********************************************************************
servera.lab.example.com    : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

探索failed_when关键词

作为最后一个练习,编辑playbook来探索failed_when关键字与任务的交互方式。

---
- hosts: slave
  remote_user: root
  tasks:
    - debug:
        msg: "I execute normally"
    - shell: "echo 'This is a string for testing error'"
      register: return_value
      failed_when: ' "error" in return_value.stdout'
    - debug:
        msg: "I never execute,Because the playbook has stopped"

上例中,一共有三个任务,第一个任务通过debug模块输出 “I execute normally”,第二个任务调用shell模块,echo了’This is a string for testing error’这句话,并且将返回值注册到了’return_value’变量中,’ failed_when’关键字与shell关键字对齐,表示其对应的条件是针对shell模块的,’ failed_when’对应的条件是 ’ “error” in return_value.stdout’,表示"error"字符串如果存在于shell模块执行后的标准输出中,则条件成立,当条件成立后,shell模块的执行状态将会被设置为失败,由于shell模块的执行状态被设置为失败,所以playbook会终止运行,于是,最后的debug模块并不会被执行.

不过,报告的失败名密可能会改变play中其余部分的行为。由于该任务在块中并且 报告了失败,因此很可能执行后续代码的rescue部分。