金鱼哥说Ansible:第五章 实施任务控制---处理任务失败

举报
金鱼哥 发表于 2022/04/13 09:56:42 2022/04/13
【摘要】 Ansible处理任务失败要这样来学才牢固

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

本章节介绍如何在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)来进行错误处理。

以上就是【金鱼哥】对 第五章 实施任务控制—处理任务失败 的简述和讲解。希望能对看到此文章的小伙伴有所帮助。

如果这篇【文章】有帮助到你,希望可以给【金鱼哥】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【运维技术】感兴趣,也欢迎关注❤️❤️❤️ 【金鱼哥】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!

111

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。