在使用ansible作自動化運維的時候,大多數狀況下都執行某些任務的時候都須要依賴某個變量的值或者是上一個任務的執行結果。如,根據facts信息中的系統版本相關的信息來肯定使用哪一種包管理器安裝軟件。Ansible提供when語句,能夠控制任務的執行流程。python
一個很簡單的when語句的例子:web
tasks: - name: "shutdown Debian flavored systems" command: /sbin/shutdown -t now when: ansible_os_family == "Debian
表示當節點主機系統爲Debian的時候,執行關機操做。
sql
在符合語句中也可使用小括號:shell
tasks: - name: "shutdown CentOS 6 and 7 systems" command: /sbin/shutdown -t now when: ansible_distribution == "CentOS" and (ansible_distribution_major_version == "6" or ansible_distribution_major_version == "7")
在`when`語句中也可使用過濾器。如,咱們想跳過一個語句執行中的錯誤,可是後續的任務的執行須要由該任務是否成功執行決定:運維
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
有時候須要將一個字符串的變量轉換爲整數來進行數字比較:ide
tasks: - shell: echo "only on Red Hat 6, derivatives, and later" when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6
在playbooks和inventory中定義的變量均可以使用,如,須要根據一個變量的bool值決定是否執行該任務:測試
vars: epic: true
條件語句:
ui
tasks: - shell: echo "This certainly is epic!" when: epic
或:
this
tasks: - shell: echo "This certainly isn't epic!" when: not epic
若是引用的變量沒有被定義,使用Jinja2的`defined`測試,能夠跳過或者是拋出錯誤:spa
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
當`when`和`with_items`一塊兒使用的時候,每一個項都會單獨被`when`語句處理:
tasks: - command: echo {{ item }} with_items: [ 0, 2, 4, 6, 8, 10 ] when: item > 5
示例:
[root@web1 ~]# cat /etc/ansible/when.yml --- - hosts: webservers remote_user: root tasks: - command: echo {{ item }} with_items: [ 1,2,3,4,5,6,8,10] when: item > 5 [root@web1 ~]# ansible-playbook /etc/ansible/when.yml PLAY [webservers] ************************************************************* GATHERING FACTS *************************************************************** ok: [192.168.1.65] TASK: [command echo {{ item }}] *********************************************** skipping: [192.168.1.65] => (item=1) skipping: [192.168.1.65] => (item=2) skipping: [192.168.1.65] => (item=3) skipping: [192.168.1.65] => (item=4) skipping: [192.168.1.65] => (item=5) changed: [192.168.1.65] => (item=6) changed: [192.168.1.65] => (item=8) changed: [192.168.1.65] => (item=10) PLAY RECAP ******************************************************************** 192.168.1.65 : ok=2 changed=1 unreachable=0 failed=0
若是須要的話,也能夠返回自定義的facts給控制節點。返回的自定義的facts變量也能夠用做下個任務的執行條件:
tasks: - name: gather site specific fact data action: site_facts - command: /usr/bin/thingy when: my_custom_fact_just_retrieved_from_the_remote_system == '1234'
在角色和包含中使用when
若是有多個任務都須要使用同一個條件語句控制。能夠將這些任務打包到一個單獨的任務文件中,而後使用`include`包含和`when`條件語句。條件語句只對包含任務文件起做用,對包含playbook文件不起做用。指定的條件語句會做用到所包含的每一個任務上:
- include: tasks/sometasks.yml when: "'reticulating splines' in output"
角色中使用when
- hosts: webservers roles: - { role: debian_stock_config, when: ansible_os_family == 'Debian' }
註冊變量
在playbook中將某個命令運行的結果保存起來,提供給後續任務使用。如,經過command模塊來判斷遠程節點上某個文件是否存在或者經過執行某個命令的獲取其返回結果,並保存起來,下個任務根據獲取的變量值來決定執行的具體操做。
register關鍵字能夠將任務執行結果保存到一個變量中,該變量能夠在模板或者playbooks文件中使用:
- name: test play hosts: all tasks: - shell: cat /etc/motd register: motd_contents - shell: echo "motd contains the word hi" when: motd_contents.stdout.find('hi') != -1
上邊中的例子中,經過註冊變量訪問返回的內容,`stdout`裏面保存了命令的標準輸出內容。註冊變量還可使用在`with_items`中,若是其保存的內容能夠轉換爲列表,或者內容自己就是個列表。若是命令的輸出自己就是列表,能夠經過`stdout_lines`訪問:
- name: registered variable usage as a with_items list hosts: all tasks: - name: retrieve the list of home directories command: ls /home register: home_dirs - name: add home dirs to the backup spooler file: path=/mnt/bkspool/{{ item }} src=/home/{{ item }} state=link with_items: home_dirs.stdout_lines # same as with_items: home_dirs.stdout.split()
示例:
[root@web1 ~]# cat /etc/ansible/rewith.yml --- - hosts: webservers remote_user: root tasks: - name: list of home dir command: ls /home register: home_dirs - name: add home dirs to the backup file: path=/tmp/back/{{ item }} src=/home/{{ item }} state=link with_items: home_dirs.stdout_lines [root@web1 ~]# ansible-playbook /etc/ansible/rewith.yml PLAY [webservers] ************************************************************* GATHERING FACTS *************************************************************** ok: [192.168.1.65] TASK: [list of home dir] ****************************************************** changed: [192.168.1.65] TASK: [add home dirs to the backup] ******************************************* changed: [192.168.1.65] => (item=1.sql) changed: [192.168.1.65] => (item=1youku.sql) changed: [192.168.1.65] => (item=liuzhenwei) changed: [192.168.1.65] => (item=tom) PLAY RECAP ******************************************************************** 192.168.1.65 : ok=3 changed=2 unreachable=0 failed=0 ###遠程節點 [root@db2 ~]# ll /tmp/back total 0 lrwxrwxrwx. 1 root root 11 Aug 4 14:37 1.sql -> /home/1.sql lrwxrwxrwx. 1 root root 16 Aug 4 14:37 1youku.sql -> /home/1youku.sql lrwxrwxrwx. 1 root root 16 Aug 4 14:37 liuzhenwei -> /home/liuzhenwei lrwxrwxrwx. 1 root root 9 Aug 4 14:37 tom -> /home/tom
在ansible中when語句的使用仍是比較多的,它能夠用來控制playbooks中任務的執行流程。相似於程序中的條件語句同樣,使得ansible能夠更好的按照運維人員的意願來對遠程節點執行特定的操做。