错误控制
ignore_errors:忽略错误failed
我们使用一下yml文件来做测试,使用yum模块安装一个不存在的软件包。
---
- name: test ignore handler
hosts: servera
tasks:
- name: 1)test ignore handler
yum:
name: notpackage
state: latest
#ignore_errors: yes
- name: 2)test debug
debug:
msg: this is debug output
正常情况下,一个playbook中如果某个tasks出现错误,则后面的tasks将不再继续执行。
TASK [Gathering Facts] ***************************************************************************************************************
ok: [servera]
TASK [1)test ignore handler] *********************************************************************************************************
fatal: [servera]: FAILED! => {"changed": false, "failures": ["No package notpackage available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
PLAY RECAP ***************************************************************************************************************************
servera : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
在一些特殊场景中,我们需要忽略当前task的异常,继续执行。
此时在task后面加上ignore_errors: yes 可控制忽略当前错误,继续执行。
添加以下代码:
ignore_errors: yes
可以忽略yum模块的错误,继续执行debug模块,运行结果为:
TASK [Gathering Facts] ***************************************************************************************************************
ok: [servera]
TASK [1)test ignore handler] *********************************************************************************************************
fatal: [servera]: FAILED! => {"changed": false, "failures": ["No package notpackage available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
...ignoring
TASK [2)test debug] ******************************************************************************************************************
ok: [servera] => {
"msg": "this is debug output"
}
force_handlers:handler错误控制
示例代码:
---
- name: test ignore handler
hosts: servera
tasks:
- name:
command: /bin/true
notify: test notify
- name: 1)test force_handlers
yum:
name: notpackage
state: latest
- name: 2)test debug
debug:
msg: this is debug output
handlers:
- name: test notify
debug:
msg: this is notify output
正常情况下,如果后续的task执行失败,notify中的handler是不会执行的。
TASK [command] ***********************************************************************************************************************
changed: [servera]
TASK [1)test force_handlers] *********************************************************************************************************
fatal: [servera]: FAILED! => {"changed": false, "failures": ["No package notpackage available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
RUNNING HANDLER [test notify] ********************************************************************************************************
使用forece_handlers可以强制执行当后续task返回为failed时,无论如何都执行handler
- name: test ignore handler
hosts: servera
force_handlers: yes
tasks:
- name:
TASK [Gathering Facts] ***************************************************************************************************************
ok: [servera]
TASK [command] ***********************************************************************************************************************
changed: [servera]
TASK [1)test force_handlers] *********************************************************************************************************
fatal: [servera]: FAILED! => {"changed": false, "failures": ["No package notpackage available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
RUNNING HANDLER [test notify] ********************************************************************************************************
ok: [servera] => {
"msg": "this is notify output"
}
failed_when:指定失败条件
示例代码:
[student@workstation wangxc]$ cat failed.yml
---
- name:
hosts: servera
tasks:
- name: run server creation script
command: /etc/hosts123
register: command_result
#failed_when: "'No such' in command_result"
#ignore_errors: yes
- name:
debug:
msg: "{{ command_result }}"
在正常情况下,改yml执行会直接输出result并终止。
TASK [Gathering Facts] ***************************************************************************************************************
ok: [servera]
TASK [run server creation script] ****************************************************************************************************
fatal: [servera]: FAILED! => {"changed": false, "cmd": "/etc/hosts123", "msg": "[Errno 2] No such file or directory: '/etc/hosts123': '/etc/hosts123'", "rc": 2}
此时,failed_when有两种用法:
1. 指定条件,当判断条件为真时,则失败。在代码中加入下面这行:
failed_when: "'No such' in command_result"
则可以正常运行后面的debug模块
TASK [run server creation script] ****************************************************************************************************
ok: [servera]
TASK [debug] *************************************************************************************************************************
ok: [servera] => {
"msg": {
"changed": false,
"cmd": "/etc/hosts123",
"failed": false,
"failed_when_result": false,
"msg": "[Errno 2] No such file or directory: '/etc/hosts123': '/etc/hosts123'",
"rc": 2
}
}
2. 条件判断,当失败的时候,输出自定义的失败信息。
上面的模块可以拆分为两部分,使用fail模块进行错误信息输出。
---
- name:
hosts: servera
tasks:
- name: run server creation script
command: /etc/hosts123
register: command_result
ignore_errors: yes
# failed_when: "'No such' in command_result"
- name:
fail:
msg: " No such file or directory"
when: "'No such' in command_result"
- name:
debug:
msg: "{{ command_result }}"
changed_when:控制changed返回
示例代码:
---
- name:
hosts: servera
tasks:
- name:
copy:
src: inventory
dest: /home/student
register: copy_res
# changed_when: "{{ copy_res['changed'] }}"
# changed_when: false
notify: debug output
- name:
debug:
msg: "{{ copy_res['changed'] }}"
handlers:
- name: debug output
debug:
msg: this is debug output
以上代码,正常情况下会输出changed并处调用handlers模块。
TASK [copy] **************************************************************************************************************************
changed: [servera]
TASK [debug] *************************************************************************************************************************
ok: [servera] => {
"msg": true
}
RUNNING HANDLER [debug output] *******************************************************************************************************
ok: [servera] => {
"msg": "this is debug output"
}
有些时候只是为了获取信息,而非真正做出了改变,我们并不想让task输出changed结果。
此时需要添加changed_when: false,即可将结果改变为ok
changed_when: false
输出结果:此时不再出发handler
TASK [Gathering Facts] ***************************************************************************************************************
ok: [servera]
TASK [copy] **************************************************************************************************************************
ok: [servera]
TASK [debug] *************************************************************************************************************************
ok: [servera] => {
"msg": false
}
还可以根据register的结果,来决定是否展示changed状态。
changed_when: "{{ copy_res['changed'] }}"
此时输出结果:
TASK [Gathering Facts] ***************************************************************************************************************
ok: [servera]
TASK [copy] **************************************************************************************************************************
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{
copy_res['changed'] }}
changed: [servera]
TASK [debug] *************************************************************************************************************************
ok: [servera] => {
"msg": true
}
RUNNING HANDLER [debug output] *******************************************************************************************************
ok: [servera] => {
"msg": "this is debug output"
}
block、rescue、always:块运行控制
- block:运行的主要任务块
- rescue:在block中定义的任务失败时,需要运行的任务
- always:始终都会运行的任务,无论block和rescue中的任务是成功还是失败
示例:
非常简单的例子,安装一个不存在的软件包,当出现错误时,执行rescue,然后执行always。
这个语法和逻辑有点类似java的try catch finally
---
- name:
hosts: servera
tasks:
- name:
block:
- name: block
yum:
name: nopackage
state: latest
rescue:
- name: rescue
debug:
msg: this is rescue
always:
- name: always
debug:
msg: this is always
运行结果
TASK [Gathering Facts] ***************************************************************************************************************
ok: [servera]
TASK [block] *************************************************************************************************************************
fatal: [servera]: FAILED! => {"changed": false, "failures": ["No package nopackage available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
TASK [rescue] ************************************************************************************************************************
ok: [servera] => {
"msg": "this is rescue"
}
TASK [always] ************************************************************************************************************************
ok: [servera] => {
"msg": "this is always"
}
当我们尝试修改yum安装的软件包为正常的包时,可以看到不再运行rescue了。
block:
- name: block
yum:
name: httpd
state: latest
结果为:
TASK [Gathering Facts] ***************************************************************************************************************
ok: [servera]
TASK [block] *************************************************************************************************************************
ok: [servera]
TASK [always] ************************************************************************************************************************
ok: [servera] => {
"msg": "this is always"
}
综合实验:处理失败的任务
- 故意安装错误的软件包,练习忽略失败ignore_errors
- 使用block等块控制语句,练习块控制
- 添加时间输出tasks,查看被管理主机的时间。由于此项并未作出改变,练习changed_when使task的结果为ok
- 练习failed_when,当安装软件包满足条件时,结果为failed
---
- name:
hosts: databases
vars:
web_package: httpd
db_package: mariadb-server
db_service: mariadb
tasks:
- name: chekc local time
command: date
register: cmd_res
#changed_when: false
- name: print local time
debug:
var: cmd_res.stdout
- name:
block:
- name: install {{ web_package }}
yum:
name: "{{ web_package }}"
state: present
#failed_when: web_package == "httpd"
#ignore_errors: yes
rescue:
- name: install {{ db_package }}
yum:
name: "{{ db_package }}"
state: present
always:
- name: start {{ db_service }} service
service:
name: "{{ db_service }}"
state: started
运行结果:这里只展示了最后一次,可以通过不同的语句来做控制
TASK [Gathering Facts] ***************************************************************************************************************
ok: [servera.lab.example.com]
TASK [chekc local time] **************************************************************************************************************
changed: [servera.lab.example.com]
TASK [print local time] **************************************************************************************************************
ok: [servera.lab.example.com] => {
"cmd_res.stdout": "Wed Mar 24 13:58:10 CST 2021"
}
TASK [install httpd] *****************************************************************************************************************
ok: [servera.lab.example.com]
TASK [start mariadb service] *********************************************************************************************************
ok: [servera.lab.example.com]