Contents
playbook条件循环控制、handlers及失败处理
循环
可以使用item循环变量+loop模块组合使用,实现普通循环
1.变量放在loop下
---
- name: 一键操作
hosts: centos70
tasks:
- name: 停止服务
yum:
name: "{{ item }}" ##引用循环变量。
state: present
loop: ##使用loop模块,要操作的对象列表。
- nginx
- vim
2.vars定义变量
定义变量,一键启动受控机上的两个服务。
---
- name: 一键操作
hosts: centos70
vars:
service_name:
- nginx
- crond
tasks:
- name: loop控制
service:
name: "{{ item }}" ##引用循环变量。
state: started
loop: "{{ service_name }}" ##使用loop模块,要操作的对象列表。
3.字典多变量循环
---
- name: 一键操作
hosts: centos70
vars:
user_info:
- user: 'test1'
uid: '2000'
- user: 'test1'
uid: '2000'
tasks:
- name: loop控制
shell: |
echo "{{ item.user }}" > /tmp/fortest
echo "{{ item.uid }}" >> /tmp/fortest
loop: "{{ user_info }}" ##使用loop模块,要操作的对象列表。
也可以这样写
vars:
user_info:
- {user:"test1",uid:"2000"}
- {user:"test2",uid:"2000"}
4.loop+register
---
- name: 一键操作
hosts: centos70
vars:
user_info:
- 'test1'
- 'test2'
tasks:
- name: loop控制
shell: |
echo "{{ item }}" 真的喜欢你
loop: "{{ user_info }}" ##使用loop模块,要操作的对象列表。
register: regist
- name: Print
debug:
var: regist ##打印输出
条件判断
- 使用when语句来进行条件判断,若条件满足,则运行任务;若条件不满足,则跳过任务。
- when语句放在模块及模块参数的后面。
使用when语句来进行条件判断,若条件满足,则运行任务;若条件不满足,则跳过任务。
when语句放在任务名称和模块同级。
条件 | 示例 |
---|---|
等于(值为字符串或数字) | max_memory == 512 |
小于/大于/小于等于/大于等于 | min_memory < 128 |
不等于 | min_memory != 512 |
变量存在 | min_memory is defined |
变量不存在 | min_memory is not defined |
布尔变量是真。1 或True或yes的值为True | memory_available |
布尔变量是假。0 或False或no的值为True | not memory_available |
变量的值是否在变量的列表中 | ansible_distribution in supported_distros |
1.根据某个变量的取值状态判断是否执行某个任务
---
- name: 卸载
hosts: centos70
vars:
service_status: true
tasks:
- name: 判断nginx是否安装
yum:
name: nginx
state: absent
when: service_status
---
- name: 卸载
hosts: centos70
vars:
service_status: false
tasks:
- name: 判断nginx是否安装
yum:
name: nginx
state: absent
when: service_status
2.根据变量是否存在判断
---
- name: 卸载
hosts: centos70
vars:
#service_status: false
tasks:
- name: 判断nginx是否安装
yum:
name: nginx
state: present
when: service_status is defined
---
- name: 卸载
hosts: centos70
vars:
service_status: false
tasks:
- name: 判断nginx是否安装
yum:
name: nginx
state: present
when: service_status is defined
3.根据事实来判断
一般需要根据受控机的状态来判断是否进行某些操作
首先查看受控机的事实
ansible centos70 -m setup |less
当系统版本大于等于7.5时,才执行条件循环语句,依次停止变量列表中的服务。
---
- name: 测试
hosts: centos70
vars:
service_name:
- nginx
- crond
tasks:
- name: 判断nginx启动
service:
name: "{{ item }}"
state: started
loop: "{{ service_name }}"
when: ansible_distribution_version >="7.5"
根据上个任务结果判断
常见的一个值是rc,rc是任务执行后输出的一个值,当rc=0时,代表任务执行成功。
---
- name: 安装服务
hosts: centos70
tasks:
- name: 判断服务是否安装
yum:
name: nginx
state: present
ignore_errors: yes ##任务执行失败直接跳过,可以继续执行后面任务。
register: regist ##注入任务输出的结果
- name: 启动服务
service:
name: nginx
state: started
when:
- regist.rc == 0 ##变量qingjun里的内容有个rc值,rc=0时才会执行第二步。
多条件判断
当有多个条件的时候可以进行多条件判断,使用and或者or关键字
and用法,所有条件都满足才执行
单行写法
when: ansible_distribution_version == "7.5" and python_version > 2.7
多行写法
when:
- ansible_distribution_version == "7.5"
- python_version > 2.7
or用法,只要有一个条件满足即可执行
单行写法
when: ansible_distribution_version == "7.5" or python_version > 2.7
多行写法
when:
ansible_distribution_version == "7.5"
or
python_version > 2.7
()组合写法,把一组表达式组合在一起,形成一个更大的表达式
when:
( ansible_distribution == "CentOS" and ansible_distribution_major_version == "7")
or
( ansible_distribution == "Fedora" and ansible_distribution_major_version == "28")
---
- name: 测试
hosts: centos70
vars:
service_name:
- nginx
- crond
tasks:
- name: 判断nginx启动
service:
name: "{{ item }}"
state: started
loop: "{{ service_name }}"
when:
( ansible_distribution == "CentOS" and ansible_distribution_major_version == "7")
or
( ansible_distribution == "Fedora" and ansible_distribution_major_version == "28")
handlers处理程序
基本了解:
handlers和tasks功能一样,也是用于处理任务的,只是它用于任务完成后需要触发进行操作的情况。
handlers和tasks是同级别,需要在tasks任务里定义notify语句,当notify语句所在的任务结果显示为changed时,才会触发handlers任务。
注意事项:
- 当tasks中有多个任务定义notify语句时,触发任务会按照handlers任务里的顺序来执行。
- 若tasks中定义多个notify语句具备相同的名称时,最终只会触发一个handlers任务。
- 即使有多个任务通知处理程序,该处理程序依然仅运行一次。如果没有任务通知处理程序,它就不会运行。
---
- name: 安装服务
hosts: centos7
tasks:
- name: 判断服务是否安装
yum:
name: nginx
state: present
ignore_errors: yes
- name: 更改服务配置文件
template:
src: nginx.conf ##将主控机上的文件传到受控机上,若文件内容发生改变则触发任务。
dest: /etc/nginx/nginx.conf
notify:
- restart nginx ##需要与handlers名称一致。
- name: 启动服务
service:
name: nginx
state: started
handlers:
- name: restart nginx ##需与notify名称一致。
service:
name: nginx
state: restarted
任务失败处理方法
1.忽略失败的任务,继续执行
- 添加参数ignore_errors: yes,可以让playbook在任务失败时继续执行。
2.强制执行失败任务
- 添加参数force_handlers: yes,针对性的适用handlers处理程序的场景。
正常情况下,当某一个任务执行失败时就会停止其他程序处理;当使用此参数时,即时前面有任务执行失败,后面的handlers也会在notify函数所在的任务发生改变时正常执行。
---
- name: 安装服务
hosts: centos70
force_handlers: yes
tasks:
- name: 判断服务是否安装
yum:
name: nginx
state: present
ignore_errors: yes
- name: 更改服务配置文件
template:
src: nginx.conf ##将主控机上的文件传到受控机上,若文件内容发生改变则触发任务。
dest: /etc/nginx/nginx.conf
notify:
- restart nginx ##需要与handlers名称一致。
- name: 启动服务
service:
name: nginx1111
state: started
handlers:
- name: restart nginx ##需与notify名称一致。
service:
name: nginx
state: restarted
3.自定义报错显示信息
- 使用failed_when指定任务失败条件,再使用fail模块指定要输出的错误信息。
- 常用于输出的错误信息太多,而我们只需要简短的错误提示即可。或者是运行的脚本里有多个任务,但其中有个任务执行失败但最终输出的信息还是changed,并非一片飘红。
#!/bin/bash
echo "failtest" >/tmp/shadow.txt
cat kskdkdks ##任务执行失败。
ls /tmp/shadow.txt ##任务执行成功
---
- name: 测试
hosts: centos70
gather_facts: no ##关闭收集事实。
tasks:
- name: 脚本测试
script: script.sh
register: regist
- debug:
var: regist
自定义报错信息
---
- name: 测试
hosts: centos70
gather_facts: no ##关闭收集事实。
tasks:
- name: 脚本测试
script: script.sh
register: regist
- name: 自定义错误信息
fail:
msg: "No such file or directory,请立即检查脚本!!!"
failed_when: "'No such file or directory' in regist.stdout"
4.自定义“changed”出现
- 特殊场景时需要playbook输出信息一直是changed,或是ok,可以使用。
如下使用template模块时,文件发生改动或第一次发送到受控机会发生改变则输出changed,之后文件不修改则一直输出ok。
此时如果要后面的输出信息一直是changed,只需在模块同级添加 changed_when,为True时则输出changed。
---
- name: 安装服务
hosts: centos70
force_handlers: yes
tasks:
- name: 更改服务配置文件
template:
src: nginx.conf ##将主控机上的文件传到受控机上,若文件内容发生改变则触发任务。
dest: /etc/nginx/nginx.conf
changed_when: true
notify:
- restart nginx ##需要与handlers名称一致。
handlers:
- name: restart nginx ##需与notify名称一致。
service:
name: nginx
state: restarted
可以看到没有添加 changed_when: true时,运行template时没有changed,添加后任务状态为changed,进而运行了handlers,所以出现了3个ok
Ansible块和错误处理
基本了解:
- block:block块中的任务是绑定在一起的,要么一起执行,要么一起不执行。
- rescue:定义要在block子句中定义的任务失败时运行的任务。
- always:不论block和rescue子句中定义的任务是成功还是失败都执行。
若block块中存在任意一个失败任务,随后会执行rescue块中的任务。block成功执行,则rescue不会执行;always始终执行。
---
- name: 测试
hosts: centos70
gather_facts: no
tasks:
- name: blocktest
block:
- name: block任务
command: echo "block"
- name: 失败任务
command: ls shadowwu
rescue:
- name: rescue任务
command: echo "rescue"
always:
- name: always任务
command: echo "always"
---
- name: 测试
hosts: centos70
gather_facts: no
tasks:
- name: blocktest
block:
- name: block任务
command: echo "block"
- name: 成功任务
command: echo "success"
rescue:
- name: rescue任务
command: echo "rescue"
always:
- name: always任务
command: echo "always"
参考
Ansible基础5——条件语句、循环语句、handlers、任务失败处理_ansible handlers-CSDN博客