when语句可以实现条件测试。如果需要根据变量、facts或此前任务的执行结果来做为某个task执行与否的前提时要用到条件测试。通过在task后添加when子句即可使用条件测试,jinja2的语法格式。
when
范例
重启所有的RedHat机器
---
- hosts: webservers
tasks:
- name: reboot redhat vps
reboot:
when: ansible_os_family=="RedHat"
对主机名进行条件判断
---
- hosts: webservers
tasks:
- name: print hostname if it matches frog
shell: wall "hostname is {{ ansible_facts.hostname }}"
when: ansible_hostname is match ("frog*")
如果服务没有启动就启动服务
---
- hosts: webservers
tasks:
- name: Check nginx service
shell: systemctl is-active nginx
register: check_nginx
ignore_errors: yes
- name: start nginx
service: name=nginx state=started
when: check_nginx.rc > 0
关闭Centos7版本的主机
---
- hosts: all
tasks:
- name: Shutdown centos7
shell: shutdown -t now
when:
- ansible_facts['distribution']=='CentOS'
- ansible_facts['distribution_major_version']=='7'
以上也可以写成
---
- hosts: all
tasks:
- name: Shutdown centos7
shell: shutdown -t now
when: ansible_distribution=='CentOS' and ansible_distribution_major_version=='7'
判断变量是否定义
---
- hosts: webservers
tasks:
- debug: msg="port is undefined"
when: port is undefined
when和循环一起使用
---
- hosts: webservers
tasks:
- name: echo item>3
debug:
msg: "{{ item }} > 3"
with_items: [1,2,3,4,5,6]
when: item > 3
failed_when
当failed_when后面的条件满足时,任务失败
范例
如果条件满足,任务失败,不执行后续任务。
---
- hosts: webservers
tasks:
- shell: echo "failed"
register: result
failed_when: "'failed' in result.stdout"
- debug: msg="success"
block
当想在满足一个条件下,执行多个任务时,就需要block分组了。
范例
---
- hosts: webservers
tasks:
- block:
- debug: msg="task1"
- debug: msg="task2"
when:
- ansible_distribution=='CentOS'
- ansible_distribution_major_version=='8'
changed_when
有些任务(例如ps aux)不会真正修改被控端但是执行完会显示黄色的changed状态,容易造成误解,可以通过changed_when来关闭。
范例
关闭changed
---
- hosts: webservers
tasks:
- shell: ps aux
changed_when: false
检查task返回结果,成功则继续向下执行。检查nginx配置文件,成功才继续启动服务。
---
- hosts: webservers
tasks:
- name: Install nginx
yum:
name: nginx
state: present
- name: Create config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Restart nginx service
- name: Syntax check
shell: nginx -t
register: result
changed_when:
- (result.stdout.find('success'))
- false
- name: Start nginx service
service:
name: nginx
state: started
handlers:
- name: Restart nginx service
service:
name: nginx
state: restarted
serial
解决ansible由于管理节点过多造成的超时问题。
默认情况下,Ansible将尝试并行管理playbook中所有的机器。对于滚动更新用例,可以使用serial关键字定义Ansible一次应管理多少主机,还可以将serial关键字指定为百分比,表示每次并行执行的主机数占总数的比例。
范例
正常情况下,假如有3个task,ansible会先执行所有主机的task1,然后执行所有主机的task2,最后执行所有主机的task3。
设置serial=1,可以让ansible每次执行完1台机器的所有task后,再去执行其他机器的task。
---
- hosts: all
serial: 1
tasks:
- debug:
msg: '"{{ ansible_nodename }}" running task1'
- debug:
msg: '"{{ ansible_nodename }}" running task2'
- debug:
msg: '"{{ ansible_nodename }}" running task3'
delegate_to
利用委派技术,可以在非当前被控主机的其它主机上执行指定操作
范例
在154.17.22.52上执行命令,而不是在localhost
---
- hosts: localhost
tasks:
- shell: wall hahaha
delegate_to: 154.17.22.52
在本地执行ifconfig
---
- hosts: webservers
tasks:
- name: show ip
local_action: command ifconfig
run_once
利用run_once可以让任务只执行一次,而不是在所有主机都执行。
范例
只显示其中一台主机的名字
---
- hosts: all
tasks:
- debug:
msg: "{{ ansible_nodename }}"
run_once: true
environment
临时修改被控端的环境变量
范例
---
- hosts: webservers
tasks:
- shell: echo $PATH > /tmp/path.log
environment:
PATH: /tmp:{{ ansible_env.PATH }}
执行结果
[root@frog448 /tmp]#cat path.log
/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
wait_for
等待条件再执行
用法
暂停10s等待端口80打开
wait_for: port=80 delay=10
等待直到锁定文件被删除
wait_for: path=/var/lock/file.lock state=absent
yaml文件的相互调用
利用include 或 include_tasks 可以在某个task中调用其它的只有task内容的yaml文件
范例
调用b.yml
---
- hosts: webservers
tasks:
- name: run job a
shell: wall job a
- name: run job b
include: b.yml
文件b.yml
---
- name: run job b
shell: wall job b
也可以将多个包含完整内容的yml文件由一个yml统一调用
范例
---
- import_playbook: task1.yml
- import_playbook: task2.yml
文件task1.yml
---
- hosts: webservers
tasks:
- name: run task1
shell: wall task1
文件task2.yml
---
- hosts: dmit
tasks:
- name: run task2
shell: wall task2