RHCE8.0实训:处理任务失败
目录
实训目的
- 在执行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部分。