VPS测评 VPS推荐 VPS优惠
Linux运维

ansible playbook如何使用when

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
未经允许不得转载:青蛙主机 » ansible playbook如何使用when

VPS相关常用工具

PING测试工具自用毛子接码站