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
相關文章
相關標籤/搜索