Ansible 自动化运维工具之when条件语句

一、When语句linux

有时候用户有可能须要某一个主机越过某一个特定的步骤.这个过程就能够简单的像在某一个特定版本的系统上少装了一个包同样或者像在一个满了的文件系统上执行清理操做同样.nginx

这些操做在Ansible上,若使用`when`语句都异常简单.When语句也含Jinja2表达式,web

第一个例子:shell

tasks:
  - name: "shutdown Debian flavored systems"
    command: /sbin/shutdown -t now
    when: ansible_os_family == "Debian"
若是你在RedHat系列linux系统执行,就不会被执行

第二个例子:apache

#cat copyfile.yml 
---
- hosts: "`host`"
  user: "`user`"
  gather_facts: True
  tasks:
    - name: Copy file to client
      copy: src=/etc/ansible/test.txt dest=/usr/local/src
      when: ansible_os_family == "Debian"
    - include: add_user.yml
      when: ansible_os_family == "Debian"
执行: 
#ansible-playbook copyfile.yml -e "host=web user=root"     --能够看到下面都skipping掉了
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [10.0.90.26]
ok: [10.0.90.25]
TASK [Copy file to client] *****************************************************
skipping: [10.0.90.25]
skipping: [10.0.90.26]
TASK [include] *****************************************************************
skipping: [10.0.90.25]
skipping: [10.0.90.26]
PLAY RECAP *********************************************************************
10.0.90.25                 : ok=1    changed=0    unreachable=0    failed=0   
10.0.90.26                 : ok=1    changed=0    unreachable=0    failed=0   
以上yml中的任务都没有执行,由于我测试机器是CentOS系统!而条件是只有当系统是Debian类型的时候执行!

PS:文件中的include模块后续会介绍。
bash

第三个例子:服务器

tasks:
  - shell: echo "only on Red Hat 6, derivatives, and later"
    when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int  >= 6
意思是只有当系统是RedHat而且版本大于等于6的时候执行

第三个例子:只有在server组或者名为server的这台服务器才执行ide

- name: Copy file to client
      copy: src=/etc/ansible/test.txt dest=/usr/local/src
      when: "host=='server'"

带管道的when语句oop

tasks:
  - command: /bin/false
    register: result
    ignore_errors: True
  - command: /bin/something
    when: result|failed
  - command: /bin/something_else
    when: result|success
  - command: /bin/still/something_else
    when: result|skipped

判断变量是否已经定义:测试

若是一个变量不存在,你可使用Jinja2的`defined`命令跳过或略过.例如:

tasks:
    - shell: echo "I've got '{{ foo }}' and am not afraid to use it!"
      when: foo is defined
    - fail: msg="Bailing out. this play requires 'bar'"
      when: bar is not defined

二、debug模块

Print statements during execution 

打印执行过程当中的语句,一般用来调试编写好的playbook语句,

Examples
# Example that prints the loopback address and gateway for each host
- debug: msg="System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}"
- debug: msg="System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}"
  when: ansible_default_ipv4.gateway is defined
- shell: /usr/bin/uptime
  register: result
- debug: var=result verbosity=2
- name: Display all variables/facts known for a host
  debug: var=hostvars[inventory_hostname] verbosity=4

生产环境遇到的一个案例:

有2台server:

第一台:10.0.90.25安装了nginx,

第二台:10.0.90.26没有安装nginx

如今我只想在没有安装nginx的server上作操做,须要经过when条件语句实现,以下:

#cat test1.yml
---
- hosts: web
  remote_user: root
  tasks:
    - name: ps
      shell: ps -ef | grep nginx | grep -v grep|wc -l
      register: nginx_num
    - debug: var=nginx_num
    - name: command 
      copy: src=/etc/ansible/server.xml dest=/root
      when: nginx_num.stdout == "0"

PS:刚开始的时候,没有添加- debug: var=nginx_num这一项,结果执行的时候,老是skipping跳过,说明条件错误后来才使用debug模块调试

执行结果:

#ansible-playbook  test1.yml 
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [10.0.90.25]
ok: [10.0.90.26]
TASK [ps] **********************************************************************
changed: [10.0.90.25]
changed: [10.0.90.26]
TASK [debug] *******************************************************************
ok: [10.0.90.25] => {
    "nginx_num": {
        "changed": true, 
        "cmd": "ps -ef | grep nginx | grep -v grep|wc -l", 
        "delta": "0:00:00.008476", 
        "end": "2016-05-19 20:40:51.742088", 
        "rc": 0, 
        "start": "2016-05-19 20:40:51.733612", 
        "stderr": "", 
        "stdout": "3", 
        "stdout_lines": [
            "3"
        ], 
        "warnings": []
    }
}
ok: [10.0.90.26] => {
    "nginx_num": {
        "changed": true, 
        "cmd": "ps -ef | grep nginx | grep -v grep|wc -l", 
        "delta": "0:00:00.009458", 
        "end": "2016-05-19 20:40:51.754993", 
        "rc": 0, 
        "start": "2016-05-19 20:40:51.745535", 
        "stderr": "", 
        "stdout": "0", 
        "stdout_lines": [
            "0"
        ], 
        "warnings": []
    }
}
TASK [command] *****************************************************************
skipping: [10.0.90.25]
changed: [10.0.90.26]
PLAY RECAP *********************************************************************
10.0.90.25                 : ok=3    changed=1    unreachable=0    failed=0   
10.0.90.26                 : ok=4    changed=2    unreachable=0    failed=0

能够看到跳过了10.0.90.25,只在10.0.90.26上执行了命令。

范例1:

#cat test2.yml 
---
- hosts: 10.0.90.25
  user: root
  gather_facts: True
  tasks:
    - name: test debug module
      debug: msg="System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}"
#ansible-playbook test2.yml 
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [10.0.90.25]
TASK [test debug module] *******************************************************
ok: [10.0.90.25] => {
    "msg": "System 10.0.90.25 has uuid 564DB430-3121-EEE4-33F1-559FEF576AC9"
}
PLAY RECAP *********************************************************************
10.0.90.25                 : ok=2    changed=0    unreachable=0    failed=0

范例2:

#cat test3.yml 
---
- hosts: 10.0.90.25
  user: root
  gather_facts: True
  tasks:
    - debug: msg="System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}"
      when: ansible_default_ipv4.gateway is defined
说明:只有当远端server的gateway配置的状况下才执行,执行结果以下:
#ansible-playbook test3.yml 
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [10.0.90.25]
TASK [debug] *******************************************************************
ok: [10.0.90.25] => {
    "msg": "System 10.0.90.25 has gateway 10.0.90.1"
}
PLAY RECAP *********************************************************************
10.0.90.25                 : ok=2    changed=0    unreachable=0    failed=0   
将10.0.90.25网关配置去掉,再一次执行:
#ansible-playbook test3.yml 
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [10.0.90.25]
TASK [debug] *******************************************************************
skipping: [10.0.90.25]
PLAY RECAP *********************************************************************
10.0.90.25                 : ok=1    changed=0    unreachable=0    failed=0   
说明:由于将远端server的网关配置去掉了,when条件不成立,就skipping了。

三、notify和Handlers

handlers 用于在发生改变时执行的操做。notify这个action可用于在每一个play的最后被触发,这样能够避免屡次有改变发生时每次都执行指定的操做,取而代之的是仅在全部的变化发生完成后一次性地执行指定操做。好比多个resources指出由于一个配置文件被改动,因此apache须要从新启动,可是从新启动的操做只会被执行一次。在notify中列出的操做称为handler也即notify调用handler中定义的操做,Handlers也是一些task的列表,经过名字来引用,他们和通常的task并无什么区别。Handlers是由通知者进行notify,若是没有被notify,handlers不会执行,无论有多少个通知者进行了notify,等到play中的全部task执行完成以后,handlers也只会被执行一次。

注意:Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操做.除此之外不多用到了,并且它会按照声明的顺序执行

以下一个例子:

自定义好httpd.conf配置文件(有变量),拷贝到/etc/httpd/conf目录,而后启动httpd,并设置开机自启动!

#cat test3.yml 
---
- hosts: web
  remote_user: root
  gather_facts: True
  vars:
    http_port: 80
    max_clients: 200
  tasks:
    - name: ensure apache is at the latest version
      yum: pkg=httpd state=latest
    - name: copy httpd config file to client 
      copy: src=/etc/ansible/httpd_test.config dest=/etc/httpd/conf/
      notify:
      - restart apache
    - name: ensure apache is running
      service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

执行:

#ansible-playbook test3.yml 
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [10.0.90.25]
ok: [10.0.90.26]
TASK [ensure apache is at the latest version] **********************************
changed: [10.0.90.26]
changed: [10.0.90.25]
TASK [copy httpd config file to client] ****************************************
changed: [10.0.90.26]
changed: [10.0.90.25]
TASK [ensure apache is running] ************************************************
ok: [10.0.90.26]
ok: [10.0.90.25]
RUNNING HANDLER [restart apache] ***********************************************
changed: [10.0.90.26]
changed: [10.0.90.25]
PLAY RECAP *********************************************************************
10.0.90.25                 : ok=5    changed=3    unreachable=0    failed=0   
10.0.90.26                 : ok=5    changed=3    unreachable=0    failed=0

注:此处定义的notify是restart,就是安装好httpd并拷贝好配置文件以后。

notify也能够是restarted、stopped、reloaded

enabled=yes是表示设置httpd开机自启动。

若是再次执行,就不会有任何改变了。由于httpd已经启动了

#ansible-playbook test3.yml 
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [10.0.90.25]
ok: [10.0.90.26]
TASK [ensure apache is at the latest version] **********************************
ok: [10.0.90.25]
ok: [10.0.90.26]
TASK [copy httpd config file to client] ****************************************
ok: [10.0.90.26]
ok: [10.0.90.25]
TASK [ensure apache is running] ************************************************
ok: [10.0.90.26]
ok: [10.0.90.25]
PLAY RECAP *********************************************************************
10.0.90.25                 : ok=4    changed=0    unreachable=0    failed=0   
10.0.90.26                 : ok=4    changed=0    unreachable=0    failed=0
相关文章
相关标签/搜索