在ansible-playbook中,也可以像其他编程语言一样进行条件判断、循环等流程控制。除此之外,还可以控制task的执行结果。
条件判断 WHEN
在ansible中,可以通过when语句来执行条件判断,只有符合条件,才会执行对应的task。
when语句和task对齐,在when语句中,变量不需要使用{{ }}括起来。
常用判断条件
条件 | 示例 |
字符串相等 | ansible_machine == "x86_64" |
数值相等 | max_memory == 512 |
小于 | min_memory < 128 |
大于 | min_memory > 128 |
小于等于 | min_memory <=512 |
大于等于 | min_memory >= 512 |
不等于 | min_memory != 512 |
变量存在 | min_memory is defined |
变量不存在 | min_memory is not defined |
变量值为 | memory_available |
变量值为 | not memory_available |
第一个变量值在第二个变量列表中 | ansible_distribution in supported_distros |
单条件判断
# when 示例
tasks:
- name: install service
yum:
name: "{{ my_service }}"
when: mysql_service is defined多条件判断
使用and表示且,or表示或。也可以使用列表,表示且的关系
# and 示例
tasks:
- name: add user when hosts in groups dev and user is defined
user:
name: "{{ my_user }}"
when: "'dev' in group_names and my_user is defined"
# 列表表示且示例 以下条件与上述条件等同
tasks:
- name: add user when hosts in groups dev and user is defined
user:
name: "{{ my_user }}"
when:
- "'dev' in group_names"
- my_user is defined
# or 示例
tasks:
- name: add user when hosts in groups dev and user is defined
user:
name: "{{ my_user }}"
when: "'dev' in group_names or 'test' in group_names"循环 loop
使用loop进行循环,一般在loop中设置一个变量,这个变量是一个列表,使用item来调用loop循环中的内容。
loop中的一个项目可以包含多个内容,使用item.name来调用循环中的内容。
loop和task对齐
# 单列表循环示例
---
- hosts: all
vars:
packages_for_install:
- firewalld
- gcc
tasks:
- name: install pascages
yum:
name: "{{ item }}"
loop: "{{ packages_for_install }}"
# 多列表循环示例
# 下面这个loop的变量中有两项,每项都包括name和groups。只循环两次
---
- hosts: all
tasks:
- name: Users exist and are in the correct groups
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
state: present
loop:
- name: jane
groups: whell
- name: joe
groups: roottask执行结果控制
在ansible-playbook中,我们可以通过一些方法控制task的结果。以便再特定情况下执行对应的操作
控制changed
Handlers
在某些情况下,我们可能希望只有task进行了实际改变时才执行某些操作,比如只有配置文件变更了,才重启对应的服务。Handlers提供了这种功能。
在handlers中定义要执行的操作名称,在task中使用notify指定要执行的操作名称。当task的结果为changed时,就会执行指定的handler
handlers和tasks对齐
notify和task对齐
执行条件
只有在task中被notify,并且这个task的状态是changed,才会执行对应的handler
handlers只有在tasks都执行成功的情况下,才会执行
多次notify的handler只会执行一次
如果handlers中定义的名称没有在tasks中notify,就不会执行
多个相同名称的handlers只会执行第一个
执行顺序
默认只有在成功执行完tasks中的所有操作后才执行handlers中的操作
handler的执行顺序按照它们在handlers中定义的顺序执行,与notify的顺序无关
强制执行handlers
即使tasks中出现错误,也执行handlers中的内容。
只是忽略tasks中的错误,实际是否执行还取决于是否notify changed。
# 示例
---
- hosts: all
force_handlers: yes
tasks:
- name:
template:
src: /var/lib/templates/demo.example.conf.template
dest: /etc/httpd/conf.d/demo.example.conf
notify:
- restart mysql
- restart apache
handlers:
- name: restart apache
service:
name: httpd
state: restarted
- name: restart mysql
service:
name: mariadb
state: restarted控制task是否更改
为了更好的使用handlers,ansible允许我们使用changed_when语句对task的结果进行变更(ok/changed)。
注意:在执行命令或脚本时,即使实际没有更改任何东西,task的结果默认也为changed
---
- hosts: all
tasks:
# task的结果为ok
- name : get Kerbores credentials as 'admin'
shell: echo "{{ krb_admin_pass }}" | kinit -f admin
changed_when: false
# 只有shell命令的结果包括"Success"时结果才为changed
- shell:
cmd: /usr/local/bin/upgrade-database
register: command_result
changed_when: "'Success' in command_result.stdout"
notify:
- restart_database
handlers:
- name: restart_database
service:
name: mariadb
state: restarted控制failed
默认情况下,如果一个task失败了,该节点上后续的task都不会继续执行
忽略错误
要忽略失败的task,继续执行其他的task,可以使用ignore_errors
tasks:
- name: Run the user creation script
command: /usr/local/bin/create_users.sh
ignore_errors: yes在出现错误时执行指定的操作
使用block-rescue-always可以执行一系列的操作
-
block 里面可以放置多个task,可以将when语句与block对齐,将条件应用于block中的所有task -
rescue 和block对齐,当block中的task执行失败时,执行这部分task -
always 和block对齐,无论block中的task是否失败,都执行这部分内容
---
- hosts: all
tasks:
- block:
# 创建一个1500M的逻辑卷
- name: create lv size 1500
lvol:
vg: research
lv: np
size: 1500
rescue:
# 如果创建失败,创建个800M的逻辑卷
- name: create lv size 800
lvol:
vg: research
lv: np
size: 800
always:
# 格式化
- name: Makes a filesystem
filesystem:
device: /dev/research/np
fstype: xfs控制task是否失败
使用failed_when控制task是否失败,当前task会执行,之后的task不会执行
使用fail模块可以使task失败并输出特定的错误消息。
---
- hosts: all
tasks:
- name : Run the user creation script
command: /usr/local/bin/create_users.sh
register: command_result
failed_when: "'Password missing' in command_result.stdout"
- name: Run the user creation script
command: /usr/local/bin/create_users.sh
register: command_result
ignore_errors: yes
- name: Report script failure
fail:
msg: "The password is missing in the output"
when: "'Password missing' in command_result.stdout"









