Ansible处理任务失败要这样来学才牢固

Ansible处理任务失败要这样来学才牢固

专栏回顾(文章描述为章节):https://blog.csdn.net/qq_41765918/category_11512932.html

本章节介绍如何在ansilbe中处理任务失败的情况,分不同情形进行讲述。

1. 管理play中任务错误

Ansible评估任务的返回代码,从而确定任务是成功还是失败。通常而言,当任务失败时,Ansible将立即在该主机上中止play的其余部分并且跳过所有后续任务,但有些时候,可能希望即使在任务失败时也继续执行play。

2. 忽略任务失败

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

[student@servera example]$ vim ignore_errors.yml
---
- name: test
  hosts: servera
  remote_user: root
  gather_facts: no
  tasks:
    - name: install httpd
      yum:
        name: packages       # 没有这个包
        state: present
      ignore_errors: yes     # 可选{yes、no}

    - name: show some massage
      debug:
        msg: "hello word"
[student@servera example]$ ansible-playbook ignore_errors.yml 

PLAY [test] ****************************************************************************

TASK [install httpd] *******************************************************************
fatal: [servera]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "msg": "No package matching 'packages' found available, installed or updated", "rc": 126, "results": ["No package matching 'packages' found available, installed or updated"]}
...ignoring

TASK [show some massage] ***************************************************************
ok: [servera] => {
    "msg": "hello word"
}

PLAY RECAP *****************************************************************************
servera: ok=2  changed=0  unreachable=0   failed=0    skipped=0    rescued=0    ignored=1

观察执行可发现跳过了报告错误的任务。

image-20211216150417525

3. 任务失败也强制执行处理程序(handlers)

通常任务失败,playbook 会终止,那么收到 play 中之前任务通知的处理程序将不会运行,如果要运行,需要在剧本中使用关键字:force_handlers:yes

[student@servera example]$ cat force_handlers.yml 
---
- name: test
  hosts: servera
  remote_user: root
  force_handlers: yes             # 强制执行handlers
  tasks:
    - name: show the msg
      debug:
        msg: "test the force_handlers"
      notify:
        - xxx
      changed_when: yes

    - name: error task
      command: ls /abc

  handlers:
    - name: xxx
      debug:
        msg: "the task is failed,but also print the msg."
[student@servera example]$ ansible-playbook force_handlers.yml 

PLAY [test] ****************************************************************************

TASK [Gathering Facts] *****************************************************************
ok: [servera]

TASK [show the msg] ********************************************************************
changed: [servera] => {
    "msg": "test the force_handlers"
}

TASK [error task] **********************************************************************
fatal: [servera]: FAILED! => {"changed": true, "cmd": ["ls", "/abc"], "delta": "0:00:00.007170", "end": "2021-12-16 12:20:06.136278", "msg": "non-zero return code", "rc": 2, "start": "2021-12-16 12:20:06.129108", "stderr": "ls: cannot access /abc: No such file or directory", "stderr_lines": ["ls: cannot access /abc: No such file or directory"], "stdout": "", "stdout_lines": []}

RUNNING HANDLER [xxx] ******************************************************************
ok: [servera] => {
    "msg": "the task is failed,but also print the msg."
}

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

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

除了可在剧本中指定强制执行外,还可以在命令行中使用 –force-handlers 选项参数,例如上述例子中,在后面加上对应的选项即可:ansible-playbook force_handlers.yml --force-handlers

还可在配置文件中添加对应配置:force_handlers = True

4. 指定任务失败的条件

方法一: 使用failed_when关键字

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

# cat test.sh
#!/bin/bash
cat /root       # 这句肯定会出错
echo "hello word"

# 注意:在playbook中执行脚本会以最后一个命令作为错误判断标准,中间错误命令不会影响整体的出错,同样也不会因为中间出错而报错

# cat playbook.yaml
---
- name: test conditions
  hosts: servera
  remote_user: root
  tasks:
    - name: test
      script:
        test.sh
      register: result
      failed_when: "'Is a directory' in result['stdout']"   # 加上报错的条件
[student@servera ~]$ ansible-playbook -i hosts  playbook.yml 
PLAY [test conditions] ******************************************************************

TASK [Gathering Facts] ******************************************************************
ok: [servera]

TASK [test] *****************************************************************************
fatal: [servera]: FAILED! => {"changed": true, "failed_when_result": true, "rc": 0, "stderr": "Shared connection to servera closed.\r\n", "stderr_lines": ["Shared connection to servera closed."], "stdout": "cat: /root: Is a directory\r\nhello word\r\n", "stdout_lines": ["cat: /root: Is a directory", "hello word"]}
	to retry, use: --limit @/home/student/playbook.retry

PLAY RECAP ******************************************************************************
servera                    : ok=1    changed=0    unreachable=0    failed=1 
方法二:使用fail模块进行报错条件

fail模块也可用于强制任务失败(主要是将杂乱的提示信息通过自己设置提示方式,达到简单、明了的目的)

---
- name: test conditions
  hosts: servera
  remote_user: root
  tasks:
    - name: test
      script:
        test.sh
      register: result

    - name: fail modules
      fail:
        msg: "There have a failed"
      when: "'Is a directory' in result['stdout']"
[student@servera ~]$ ansible-playbook -i hosts  playbook.yml 
PLAY [test conditions] ****************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [servera]

TASK [test] ***************************************************************************
changed: [servera]

TASK [fail modules] *******************************************************************
fatal: [servera]: FAILED! => {"changed": false, "msg": "There have a failed"}
	to retry, use: --limit @/home/student/playbook.retry

PLAY RECAP ****************************************************************************
servera                    : ok=2    changed=1    unreachable=0    failed=1

5. 指定任务何时报告“changed”结果

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

changed_when关键字可用于控制任务在何时报告它已进行了更改。

演示一:
---
- name: test conditions
  hosts: servera
  tasks:
    - name: test
      shell: echo "hello word"
      changed_when: false      #可选{true、false}

True,无论是否成功执行,报告返回结果都为changed。如果为False,在task没有错误的情况下,始终返回ok。

演示二:
---
- name: test conditions
  hosts: servera
  tasks:
    - name: test
      command: echo "hello word"
      register: result
      changed_when: "'hello word' in result.stdout"
#      changed_when: "'hello word' not in result.stdout"

# 因为在result[‘stdout’]中有hello word ,所以被认定为是true,所以就显示changed;如果是不在,即为false,就会显示OK。

6. Ansible块(block)和错误处理

在playbook中,块是对任务进行逻辑分组的子句,可用于控制任务的执行方式。也可结合rescue和always语句来处理错误。如果块中的任何任务失败,则执行其rescue块中的任务来进行恢复。在block子句中的任务以及rescue子句中的任务(如果出现故障才运行)运行之后,always子句中的任务才运行。

  • block:定义要运行的主要任务
  • rescue:定义要在block子句中定义的任务失败时运行的任务
  • always:定义始终都独立运行的任务,不论block和rescue子句中定义的任务是成功还是失败
[student@servera example]$ cat block.yml
---
- name: test block
  hosts: servera
  vars:
    file_name: test
  tasks:
    - name: test block
      block:
        - name: block1
          command: ls /tmp
        - name: block2
          command: "ls /tmp/{{ file_name }}"             # 若文件不存在,执行rescue
      rescue:
        - name: "touch the {{ file_name }}"              # 创建此文件
          file:
            name: "/tmp/{{ file_name }}"
            state: touch
      always:                                          # 无论block成功与否,都执行always
        - name: print
          command: echo "\(@^0^@)/"
          register: result
        - debug:
            msg: "{{ result.stdout }}"

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

[student@servera example]$ ansible-playbook block.yml 

PLAY [test block] *********************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [servera]

TASK [block1] **************************************************************************
changed: [servera]

TASK [block2] **************************************************************************
fatal: [servera]: FAILED! => {"changed": true, "cmd": ["ls", "/tmp/test"], "delta": "0:00:00.008167", "end": "2021-12-16 14:48:40.867397", "msg": "non-zero return code", "rc": 2, "start": "2021-12-16 14:48:40.859230", "stderr": "ls: cannot access /tmp/test: No such file or directory", "stderr_lines": ["ls: cannot access /tmp/test: No such file or directory"], "stdout": "", "stdout_lines": []}

TASK [touch the test] ******************************************************************
changed: [servera]

TASK [print] ***************************************************************************
changed: [servera]

TASK [debug] ***************************************************************************
ok: [servera] => {
    "msg": "\\(@^0^@)/"
}

PLAY RECAP *****************************************************************************
servera: ok=5   changed=3  unreachable=0  failed=0   skipped=0    rescued=1    ignored=0

image-20211216150524785

总结

  • 介绍如何忽略任务失败而继续进行任务。
  • 使用相关设置让任务失败也强制执行处理程序。
  • 可指定任务失败的条件。
  • 可指定任务何时报告“changed”结果。
  • 介绍了如何使用块(block)来进行错误处理。
  • 若喜欢金鱼哥的文章,顺手点个赞。也可点个关注,因为后续会不断上干货。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT民工金鱼哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值