环境版本说明
- RedHat9 [Red Hat Enterprise Linux release 9.0]
- Ansible [core 2.13.3]
- Python [3.9.10]
- jinja [3.1.2]
1. 忽略任务失败
- Ansible评估各任务的返回代码,从而确定任务是成功还是失败
- 通常而言,当任务失败时,Ansible将立即在该主机上终止play的其余部分并且跳过所有后续任务
- 通常洗完遇到任务失败时,仍能继续执行Play
- 忽略任务失败
在serverb上安装discuz软件包,然后创建目录,因为源中默认不存在discuz软件包,所以会报错
[Step1]:
编写playbook
vim ignore_errors.yml
# 写入下列内容
---
- name: play1
hosts: serverb
tasks:
- name: Install the latest version of Discuz
ansible.builtin.yum:
name: discuz
state: latest
- name: Create Dir
ansible.builtin.shell:
cmd: mkdir /discuz
[Step2]:
验证playbook语法
ansible-navigator run ignore_errors.yml -m stdout --syntax-check
[Step3]:
运行playbook,没有处理任务失败,在失败后会直接暂停执行
ansible-navigator run ignore_errors.yml -m stdout
[Step4]:
验证:查看serverb上是否新建目录
ssh root@serverb "ls -l / | grep discuz"
[Step5]:
在playbook中添加忽略任务失败语句
vim ignore_errors.yml
# 写入下列内容
---
- name: play1
hosts: serverb
tasks:
- name: Install the latest version of Discuz
ansible.builtin.yum:
name: discuz
state: latest
ignore_errors: yes # 忽略失败任务
- name: Create Dir
ansible.builtin.shell:
cmd: mkdir /discuz
[Step6]:
验证:查看serverb上是否新建目录
ssh root@serverb "ls -l / | grep discuz"
2. 任务失败后强制执行处理程序
在通常情况下,如果任务失败会导致Play中止,如果在Play中的设置 force_handlers: yes
关键字,即使Play 因为后续任务失败而中止,也会调用被预先定义的处理程序(handlers中预先定义的模块)。
如果给任务中的Play设置了ignore_errors: yes
,则任务失败时,还是会忽略任务失败,就算在后面设置了force_handlers: no
,Play和处理程序还是会保持运行,除非有其它任务导致Play失败。
处理程序在任务报告changed结果时获得通知,在任务报告ok或failed结果时不会获得通知。如果在Play上设置了force_handlers: yes
,即使后续任务失败导致Play失败,也会运行预定义的处理程序。否则,当Play失败时,处理程序完全不会运行。
在Play上设置force_handlers: yes
不会使任务报告 ok 或 failed 而获得通知;而只会使 Play 失败已获得通知的处理程序运行。
[Step1]:
编写playbook
vim force_handlers.yml
# 写入下列内容
---
- name: play1
hosts: serverb
force_handlers: yes # 在任务是失败时强制执行处理程序
tasks:
- name: Restart service httpd, in all cases
ansible.builtin.service:
name: httpd
state: restarted
- name: Install the latest version of notapkg
ansible.builtin.dnf:
name: notapkg
state: latest
handlers: # 失败时强制执行
- name: Restart service httpd, in all cases
ansible.builtin.service:
name: httpd
state: restarted
[Step2]:
验证playbook语法
ansible-navigator run force_handlers.yml -m stdout --syntax-check
[Step3]:
运行playbook
ansible-navigator run force_handlers.yml -m stdout
3. Ansible块和错误处理
- Block:定义要运行的主要任务
- Rescue:定义在block子句中定义的任务失败时运行的任务
- Always:定义始终都在独立运行的任务
3.1 Block
Block可以理解为是一个区域,多个模块都使用相同的条件语句,可以放置在同一个Block下。
原Playbook:在serverb上新建文件和新用户
---
- name: blcok
hosts: all
tasks:
- name: touch file # 在serverb上新建block.txt文件
ansible.builtin.shell:
cmd: touch block.txt
when: inventory_hostname == "serverb"
- name: Add the user 'block' # 在serverb上新建用户 block
ansible.builtin.user:
name: block
when: inventory_hostname == "serverb"
使用block后Playbook:减少when条件语句
---
- name: blcok
hosts: all
tasks:
- block: # 概念类似组,when条件针对block组内用户生效
- name: touch file
ansible.builtin.shell: touch block.txt
- name: Add the user 'block'
ansible.builtin.user:
name: block
when: inventory_hostname == "serverb"
验证:查看文件和创建的用户
ssh root@serverb "ls -l;tail -n 1 /etc/passwd"
3.2 rescue和always
可以将Block理解为IF语句,然后rescue理解为else语句,当Block满足则运行Block,不满足则运行rescue。不管是否满足Block还是rescue,都执行always。
如果在serverc上可以安装http软件包则安装,否则安装httpd软件包,无论软件包是否安装都关闭serverc防火墙
[Step1]:
编写playbook
vim always.yml
# 写入下列内容
---
- name: play1
hosts: all
tasks:
- block:
- name: Install the latest version of http
ansible.builtin.dnf: # 安装http软件包
name: http
state: latest
rescue:
- name: Install the latest version of httpd
ansible.builtin.dnf: # 安装httpd软件包
name: httpd
state: latest
when: inventory_hostname == "serverc" # 限定主机为serverc
always: # always的对象是上面的when条件语句
- name: Stop service firewalld, if started
ansible.builtin.service: # 关闭防火墙
name: firewalld
state: stopped
[Step2]:
验证playbook语法
ansible-navigator run always.yml -m stdout --syntax-check
[Step3]:
运行playbook
ansible-navigator run always.yml -m stdout
[Step4]:
验证:查看serverc上的防火墙和软件包安装情况
ansible serverc -m shell -a 'rpm -qa | grep httpd'
ansible serverc -m shell -a 'systemctl status h'