ansible的任务执行控制
- 一、循环
- 1、简单循环
- 2、循环散列或字典列表
- 二、条件判定
- 1、when条件语句
- 2、条件判断
- 三、触发器
- 四、 处理失败任务
- 1、ignore_errors
- 2、force_handlers
- 3、changed_when
- 4、failed_when
- 5、block
- 实验环境
此处参考:
共四台主机,server1~server4,server1为ansible主机,其他三台为被控端,均开启火墙;
将server2~server4加入资源清单;
在server1主机上拥有ansible用户skk
,并单独配置ansible环境,在其他三台主机上创建devops
用户,用visudo
免密授权,将server1的公钥分发给其他三台主机的devops
用户。
一、循环
1、简单循环
使用loop赋值列表的格式:
loop: ##赋值列表
- value1
- value2
- ...
{{item}} ##迭代变量名称
(1)在playbook中使用
vim user.yml
---
- name: create user
hosts: server2
tasks:
- name: create user
user:
name: "{{item}}" ##迭代变量名称
state: present
loop: ##赋值列表
- user1
- user2
- user3
建立用户成功
(2)通过文件定义变量
编写变量文件
vim user_list.yml
---
USERS: ##定义变量
- user1
- user2
- user3
编写yaml文件
vim user.yml
---
- name: create user
hosts: server2
vars_files: ./user_list.yml
tasks:
- name: create user
user:
name: "{{item}}"
state: absent
remove: yes
loop:
"{{USERS}}" ##此处赋值时不用加-
删除用户成功
2、循环散列或字典列表
- 可以赋予不同的服务不同的状态
示例:为server3主机建立用户,并赋予密码
(1)此处的密码必须是加密过后的,使用rhel8
的openssl passwd -6
将密码加密
vim user.yml
---
- name: create user
hosts: server3
tasks:
- name: create user
user:
name: "{{ item.user }}"
password: "{{ item.passwd }}"
state: present
loop:
- user: user1
passwd: "$6$P2MmG.dGe59uEe0R$SVmq6oojHWvYVK.BZhmL7pWjb7zVKRkUM.Rp2kFbLtl7jS570ZClaVPRZkX9BtfkqlLLCbTrlG7a04YRi/wz3."
- user: user2
passwd: "$6$YZcSU4GwSVBnw.ro$wQ0fAO9lB2M1Nwu9tVyBoGiEV/qOzQGBY.UHw2pQiq0GEjYpNW3c2FtG/wWZ0iVpqZi.iCo1x18LjpJg9tGTK/"
- user: user3
passwd: "$6$lqv/hz7ynndCR9NR$BmhKzFUsW4XzP9x9eAXv782gYBnxWUGFnh1qYExYwof5PSPk36GnlDKjjeygCSohM0cpncmk.1mkljEAgX3FQ1"
测试连接:
二、条件判定
1、when条件语句
此条件代表两者都满足时
when:
- 条件1
- 条件2
此条件代表两者满足一个即可
when:
- 条件1 or 条件2
也可以表示为
when:
- 条件1
or
条件2
示例:检测文件是否存在ignore_errors: yes
:当文件不存在时,系统会判定失败,没有返回值,加此参数可以忽略错误
vim exist.yml
---
- name: test
hosts: demo
tasks:
- name: test
shell: test -e /mnt/file ##使用shell模块检测文件是否存在
ignore_errors: yes
register: OUTPUT ##将得到的结果注册给OUTPUT变量
- name: show message
debug:
msg: /mnt/file is exist
when: OUTPUT.rc == 0 ##输出的结果rc部分为0,文件存在
- name: show message
debug:
msg: /mnt/file is not exist
when: OUTPUT.rc == 1 ##输出的结果rc部分为1,文件不存在
在server4主机上创建/mnt/file
,在server2和server3上不创建,执行yaml文件
2、条件判断
| value |
| value |
| value |
| value |
| value |
| value |
| value is defined(变量存在) |
| value is not defined(变量不存在) |
| value is in value(变量为) |
| value is not in value(变量不为) |
bool变量为 | value(value的值为true) |
bool变量 | not value(value的值为false) value in value2(value的值在value2列表中) |
示例:添加磁盘,利用条件语句对磁盘进行检测
(1)为server2主机添加磁盘
通过ansible语句可以检测到
ansible server2 -m shell -a "fdisk -l /dev/vdb"
(2)编写yaml文件,检测是否存在vdb磁盘
vim vdb.yml
---
- name: test
hosts: demo
tasks:
- name: show message
debug:
msg: /dev/vdb is exist
when:
- ansible_facts['devices']['vdb'] is defined ##vdb存在时
- inventory_hostname in "server2" ##hostname为server2时,与上面条件须同时满足
- name: show message
debug:
msg: /dev/vdb is not find
when:
- ansible_facts['devices']['vdb'] is not defined
or
inventory_hostname not in "server2" ##vdb不存在或hostname不为server2时,也可以写到一行
(3)执行yaml文件,得到结果
三、触发器
notify
:触发器当遇到更改时触发handlers
handlers
:触发器触发后执行的动作
示例:安装下载vsftpd并修改访问家目录
1、编写yaml文件
vim vsftpd.yml
---
- name: vsftpd
hosts: server4
tasks:
- name: install vsftpd
yum:
name: vsftpd
state: present
- name: start vsftpd
service:
name: vsftpd
state: started
enabled: yes
notify:
- firewalld ##当vsftpd服务被设定开机自启后,触发firewalld模块
- name: vsftpd.conf
lineinfile:
path: /etc/vsftpd/vsftpd.conf
line: "anon_root=/mnt" ##修改访问家目录
regexp: "^anon_root" ##替换的行
backrefs: no ##匹配到时替换,没匹配到时,文件结尾添加一行
notify:
- restart vsftpd ##当文件替换后,触发模块重启服务
handlers: ##被触发后的模块,注意此处与tasks对齐
- name: firewalld
firewalld:
service: ftp
state: enabled
permanent: yes
immediate: yes
- name: restart vsftpd
service:
name: vsftpd
state: restarted
2、执行yaml文件
3、在server4的/mnt/file
中添加内容,匿名访问测试
四、 处理失败任务
1、ignore_errors
作用:当play遇到任务失败时会终止,ignore_errors: yes
将会忽略任务失败使下面的任务继续运行
示例:安装一个不存在的服务
vim ignore.yml
---
- name: ignore_errors
hosts: server3
tasks:
- name: install haha
yum:
name: haha
state: present
ignore_errors: yes ##忽略错误
- name: debug
debug:
msg: heloo lll
2、force_handlers
作用:当任务失败后play被终止也会调用触发器进程
示例:安装一个不存在的服务,任务失败play终止后仍会有触发
注意去除 ignore_errors: yes 的干扰
vim force.yml
---
- name: force_handlers
hosts: server3
force_handlers: yes ##任务失败后仍触发
tasks:
- name: hostname
shell:
hostname
register: info ##使用注册变量
notify:
- debug
- name: install haha
yum:
name: haha
state: present
handlers:
- name: debug
debug:
msg: "{{ info['stdout'] }}" ##展示变量info的输出变量
3、changed_when
作用:控制任务在何时报告它已进行更改,抑制更改
示例:测试changed_when: true
vim changed.yml
---
- name: test
hosts: server4
tasks:
- name: install vsftpd
yum:
name: vsftpd
state: present
changed_when: true ##当检测到vsftpd安装后(无论是刚安装还是之前已安装),报告发生改变
server4的vsftpd之前已经安装,应该显示为绿色,但此处显示为黄色
示例:测试changed_when: false
vim changed.yml
---
- name: test
hosts: server4
tasks:
- name: remove vsftpd
yum:
name: vsftpd
state: absent
changed_when: false ##当检测到vsftpd被卸载时,报告不改变
此处卸载了vsftpd,应该有改变为黄色,但这里为绿色
4、failed_when
作用:当符合条件时强制任务失败,但不会更改任务本身的行为
示例:建立文件,报错,但实质已经建立
vim failed.yml
---
- name: test
hosts: server2
tasks:
- name: touch file
file:
path: /mnt/failedfile
state: touch
failed_when: true ##当文件创建后报错
但实际文件创建成功
示例:在不存在的目录下创建文件,却报告成功
vim failed.yml
---
- name: test
hosts: server2
tasks:
- name: touch file
file:
path: /mnt/haha/linuxfile
state: touch
failed_when: false ##当文件未创建时不报错
文件自然没有创建
5、block
block
:定义要运行的任务rescue
:定义当block
句子中出现失败任务后运行的任务always
:定义最终独立运行的任务
示例1:此时/mnt/file
存在
vim block.yml
---
- name: test
hosts: server4
tasks:
- name: check file
block:
- name: test
shell: test -e /mnt/file
- name: debug
debug:
msg: /mnt/file is exist
rescue:
- name: debug
debug:
msg: /mnt/file is not exist
always:
- name:
debug:
msg: good night!
所以block句子中没有失败,所以不会执行rescue模块
示例2:此时/mnt/file
不存在
再次执行block.yml
,因为block句子中有失败,所以执行rescue模块