ansible支持變量,用於存儲會在整個項目中重復使用到的一些值。以簡化項目的創建與維護,降低出錯的機率。
變量的定義:
- 變量名應該由字母、數字下划數組成
- 變量名必須以字母開頭
- ansible內置關鍵字不能作為變量名
1. 在Inventory中定義變量
1.1. 定義主機變量
1.1.1. 內置主機變量
所謂內置變量其實就是ansible.cfg配置文件中的選項,在其前加上ansible_
即成為內置變量。當然內置變擁有比ansible.cfg中選項更高的優先級,而且針對不同的主機,可以定義不同的值。
# 一般連接 ansible_ssh_host #用於指定被管理的主機的真實IP ansible_ssh_port #用於指定連接到被管理主機的ssh端口號,默認是22 ansible_ssh_user #ssh連接時默認使用的用戶名 # 特定ssh連接 ansible_connection #SSH連接的類型:local, ssh, paramiko,在ansible 1.2 之前默認是paramiko,后來智能選擇,優先使用基於ControlPersist的ssh(如果支持的話) ansible_ssh_pass #ssh連接時的密碼 ansible_ssh_private_key_file #秘鑰文件路徑,如果不想使用ssh-agent管理秘鑰文件時可以使用此選項 ansible_ssh_executable #如果ssh指令不在默認路徑當中,可以使用該變量來定義其路徑 # 特權升級 ansible_become #相當於ansible_sudo或者ansible_su,允許強制特權升級 ansible_become_user #通過特權升級到的用戶,相當於ansible_sudo_user或者ansible_su_user ansible_become_pass # 提升特權時,如果需要密碼的話,可以通過該變量指定,相當於ansible_sudo_pass或者ansible_su_pass ansible_sudo_exec #如果sudo命令不在默認路徑,需要指定sudo命令路徑 # 遠程主機環境參數 ansible_shell_executable # 設置目標機上使用的shell,默認為/bin/sh ansible_python_interpreter #用來指定python解釋器的路徑,默認為/usr/bin/python 同樣可以指定ruby 、perl 的路徑 ansible_*_interpreter #其他解釋器路徑,用法與ansible_python_interpreter類似,這里"*"可以是ruby或才perl等其他語言
下面是一個簡單的示例:
192.168.132.131 ansible_ssh_user=ansible ansible_become_user=user1 ansible_become_method=sudo ansible_become_pass="redhat" 192.168.132.132 ansible_python_interpreter=/usr/local/python3/bin/python3
192.168.132.133 ntpserver=192.168.132.134 zabbixserer=192.168.132.134
1.2 定義主機組變量
變量也可以通過組名,應用到組內的所有成員:
[web] node1 node2 [web:vars] ntpserver=192.168.132.134
[root@node1 ansible]# vim vars_play1.yml
- hosts: web tasks: - package: name: ntpdate state: present - cron: name: sync time minute: "*/5" job: "ntpdate {{ ntpserver }}"
[root@node1 ansible]# ansible-playbook vars_play1.yml
PLAY [web] ******************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************** ok: [node1] ok: [node2] TASK [package] **************************************************************************************************** changed: [node2] changed: [node1] TASK [cron] ******************************************************************************************************* changed: [node1] changed: [node2] PLAY RECAP ******************************************************************************************************** node1 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 node2 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
檢查
[root@node1 ansible]# ansible web -m shell -a "crontab -l"
node2 | CHANGED | rc=0 >> #Ansible: tectcron * * * * * echo `date` >> /tmp/test.txt #Ansible: sync time */5 * * * * ntpdate 192.168.132.134 node1 | CHANGED | rc=0 >> #Ansible: tectcron * * * * * echo `date` >> /tmp/test.txt #Ansible: sync time */5 * * * * ntpdate 192.168.132.134
變量的優先級,主機變量擁有最高的優先級
[web] node1 ntpserver=ntp1.aliyun.com node2 [web:vars] ntpserver=192.168.132.134
2. 在Playbook中定義變量
2.1. 變量的定義方式
2.1.1. 通過vars關鍵字定義
擁有比主機和主機組更高的優先級
前面的一個示例:
- hosts: web vars: ntpserver: ntp2.aliyun.com tasks: - package: name: ntpdate state: present - cron: name: sync time minute: "*/5" job: "ntpdate {{ ntpserver }}"
[root@node1 ansible]# ansible-playbook vars_play1.yml
[root@node1 ansible]# ansible web -m shell -a "crontab -l"
node1 | CHANGED | rc=0 >> #Ansible: tectcron * * * * * echo `date` >> /tmp/test.txt #Ansible: sync time */5 * * * * ntpdate ntp2.aliyun.com node2 | CHANGED | rc=0 >> #Ansible: tectcron * * * * * echo `date` >> /tmp/test.txt #Ansible: sync time */5 * * * * ntpdate ntp2.aliyun.com
自定義變量,debug調試
- hosts: web vars: ntpserver: ntp2.aliyun.com # users: [{"name":"natasha","gender"},{"name":"tom","gender":"male" }] users: - name: natasha gender: famale - name: tom gender: male tasks: - debug: msg: "print users: {{ users }}" - debug: var: users
[root@node1 ansible]# ansible-playbook vars_play1.yml
PLAY [web] ************************************************************************************************************************************ TASK [debug] ********************************************************************************************************************************** ok: [node1] => { "msg": "print users: [{u'gender': u'famale', u'name': u'natasha'}, {u'gender': u'male', u'name': u'tom'}]" } ok: [node2] => { "msg": "print users: [{u'gender': u'famale', u'name': u'natasha'}, {u'gender': u'male', u'name': u'tom'}]" } TASK [debug] ********************************************************************************************************************************** ok: [node1] => { "users": [ { "gender": "famale", "name": "natasha" }, { "gender": "male", "name": "tom" } ] } ok: [node2] => { "users": [ { "gender": "famale", "name": "natasha" }, { "gender": "male", "name": "tom" } ] }
2.1.2. 通過vars_files關鍵字引入變量文件
下面是一個簡單示例:
- hosts: web vars_files: - ntp.yml - users.yml tasks: - package: name: ntpdate state: present - cron: name: sync time minute: "*/5" job: "ntpdate {{ ntpserver }}" - debug: msg: "print users: {{ users }}" - debug: var: users
[root@node1 ansible]# vim ntp.yml
ntpserver: ntp3.aliyun.com
[root@node1 ansible]# vim users.yml
users: - name: natasha gender: famale - name: tom gender: male
變量的定義格式是成鍵值對出現的,鍵值對之間可以嵌套,最終形成一個大字典,效果和前面一樣
2.2 在playbook中通過host_vars和group_vars目錄定義變量
定義inventory
demo5.example.com
[datacenter1]
demo1.example.com
demo2.example.com
[datacenter2]
demo3.example.com
demo4.example.com
[webserver]
demo1.example.com
demo2.example.com
demo3.example.com
[mysqlserver]
demo4.example.com
demo5.example.com
[datacenters:children]
datacenter1
datacenter2
創建兩個目錄
[root@node1 ansible]# mkdir group_vars
[root@node1 ansible]# mkdir host_vars
這兩個目錄用於存放變量的配置文件
主機組使用變量
[root@node1 ansible]# vim group_vars/datacenter1 package: "tomacat1" [root@node1 ansible]# vim group_vars/datacenter2 package: "tomacat2" [root@node1 ansible]# vim group_vars/datacenters package: "tomacat3" [root@node1 ansible]# vim group_vars/mysqlserver package: "mysql"
主機變量
[root@node1 ansible]# vim host_vars/demo1.example.com package: "nginx1" [root@node1 ansible]# vim host_vars/demo3.example.com package: "nginx3" [root@node1 ansible]# vim host_vars/demo5.example.com package: "nginx5"
目錄結構
[root@node1 ansible]# tree
.
├── ansible.cfg
├── group_vars
│ ├── datacenter1
│ ├── datacenter2
│ ├── datacenters
│ └── mysqlserver
├── hosts
├── host_vars
│ ├── demo1.example.com
│ ├── demo3.example.com
│ └── demo5.example.com
├── inventory
└── roles
[root@node1 ansible]# cat datacenter.yml
- hosts: datacenter1 tasks: - name: fetch vars debug: msg: "{{ package}}"
執行
TASK [fetch vars] ***************************************************************************************************************************** ok: [demo1.example.com] => { "msg": "nginx1" } ok: [demo2.example.com] => { "msg": "tomacat1" }
[root@node1 ansible]# vim datacenter.yml
- hosts: all tasks: - name: fetch vars debug: msg: "{{ package}}"
root@node1 ansible]# ansible-playbook datacenter.yml
TASK [fetch vars] ***************************************************************************************************************************** ok: [demo4.example.com] => { "msg": "tomcat2" } ok: [demo5.example.com] => { "msg": "nginx5" } ok: [demo1.example.com] => { "msg": "nginx1" } ok: [demo2.example.com] => { "msg": "tomacat1" } ok: [demo3.example.com] => { "msg": "nginx3" }
如果主機組定義的變量與主機沖突,主機變量優先級最高
2.3 注冊變量
在有些時候,可能需要將某一條任務執行的結果保存下來,以便在接下的任務中調用或者做些判斷。可以通過register關鍵字來實現將某一任務結果保存為一個變量。
注冊變量的應用場景:
- 在一台遠端的服務器獲取一個目錄下的一列表的文件,然后下載這些文件
- 在handler執行之前,發現前面一個task發生了changed,然后執行一個指定的task
- 獲取遠端服務器的ssh key的內容,構建出known_hosts文件
[root@node1 ansible]# vim var_test.yml
- hosts: demo5.example.com tasks: - name: list /home shell: ls /home register: list - debug: var: list
[root@node1 ansible]# ansible-playbook var_test.yml
PLAY [demo5.example.com] ********************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************ ok: [demo5.example.com] TASK [list /home] ***************************************************************************************************************************** changed: [demo5.example.com] TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { "list": { "changed": true, "cmd": "ls /home", "delta": "0:00:00.005802", "end": "2020-01-28 13:09:38.768490", "failed": false, "rc": 0, #命令執行的正常的返回 "start": "2020-01-28 13:09:38.762688", "stderr": "", "stderr_lines": [], "stdout": "ansible\njoy", #換行輸出 "stdout_lines": [ #這個包含也是的是正常的返回 "ansible", "joy" ] } } PLAY RECAP ************************************************************************************************************************************ demo5.example.com : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
當shell執行報錯,錯誤可以使用ignore_error忽略,繼續執行
[root@node1 ansible]# vim var_test.yml
- hosts: demo5.example.com tasks: - name: list /home shell: ls /home register: list - shell: error_test register: error ignore_errors: True - debug: var: list - debug: var: error
[root@node1 ansible]# ansible-playbook var_test.yml
PLAY [demo5.example.com] ********************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************ ok: [demo5.example.com] TASK [list /home] ***************************************************************************************************************************** changed: [demo5.example.com] TASK [shell] ********************************************************************************************************************************** fatal: [demo5.example.com]: FAILED! => {"changed": true, "cmd": "error_test", "delta": "0:00:00.004308", "end": "2020-01-28 13:21:53.726688", "msg": "non-zero return code", "rc": 127, "start": "2020-01-28 13:21:53.722380", "stderr": "/bin/sh: error_test: command not found", "stderr_lines": ["/bin/sh: error_test: command not found"], "stdout": "", "stdout_lines": []} ...ignoring TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { "list": { "changed": true, "cmd": "ls /home", "delta": "0:00:00.005806", "end": "2020-01-28 13:21:53.151761", "failed": false, "rc": 0, #正常返回 "start": "2020-01-28 13:21:53.145955", "stderr": "", "stderr_lines": [], "stdout": "ansible\njoy", "stdout_lines": [ "ansible", "joy" ] } } TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { "error": { "changed": true, "cmd": "error_test", "delta": "0:00:00.004308", "end": "2020-01-28 13:21:53.726688", "failed": true, "msg": "non-zero return code", "rc": 127, #命令不存在返回 "start": "2020-01-28 13:21:53.722380", "stderr": "/bin/sh: error_test: command not found", #找到不到命令 "stderr_lines": [ "/bin/sh: error_test: command not found" ], "stdout": "", "stdout_lines": [] } } PLAY RECAP ************************************************************************************************************************************ demo5.example.com : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
2.4 通過命令行設置變量
- hosts: '{{ hosts }}' remote_user: '{{ user }}' tasks: - debug: var: hosts - debug: var: user
[root@node1 ansible]# ansible-playbook var_test.yml --extra-vars "hosts=demo5.example.com user=ansible"
或者
[root@node1 ansible]# ansible-playbook var_test.yml --extra-vars '{"hosts":"demo5.example.com","user":"ansible"}'
TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { "hosts": "demo5.example.com" } TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { "user": "ansible" }
2.5 變量的使用和調試
定義一個變量文件
[root@node1 ansible]# vim users.yml
users: - name: natash gender: female hobby: - swimming - running - name: tom gender: male hobby: - football - basketball - sleepping
[root@node1 ansible]# vim use_users.yml
- hosts: demo5.example.com vars_files: #調用變量文件 - users.yml tasks: - debug: var: users #獲取users變量的信息結構等
[root@node1 ansible]# ansible-playbook use_users.yml
TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { #user變量的結構 "users": [ #列表有序 { "gender": "female", "hobby": [ "swimming", "running" ], "name": "natash" }, { "gender": "male", "hobby": [ "football", "basketball", "sleepping" ], "name": "tom" } ] }
獲取user當中,第一個用戶的第一個愛好
- hosts: demo5.example.com vars_files: - users.yml tasks: - debug: var: users[0].hobby[0] #第一個用戶的第一個愛好 - debug: msg: "{{ users[1].hobby[2] }}" #第二個用戶的第三個愛好
執行輸出
TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { "users[0].hobby[0]": "swimming" } TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { "msg": "sleepping" }
重新定義變量
[root@node1 ansible]# vim users.yml
users: natash: - name: natash gender: female hobby: - swimming - running tom: - name: tom gender: male hobby: - football - basketball - sleepping
[root@node1 ansible]# vim use_users.yml
- hosts: demo5.example.com vars_files: - users.yml tasks: - debug: var: users.natash[0].hobby[0] - debug: msg: "{{ users.tom[0].hobby }}" #獲取所有愛好
[root@node1 ansible]# ansible-playbook use_users.yml
TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { "users.natash[0].hobby[0]": "swimming" } TASK [debug] ********************************************************************************************************************************** ok: [demo5.example.com] => { "msg": [ "football", "basketball", "sleepping" ] }
另外的引用變量方式
- debug: var: users.natash.0.hobby.0 - debug: msg: "{{ users.tom.0.hobby }}" - debug: msg: "{{ users['tom'][0]['hobby'] }}"
2.6 關於debug介紹
關於輸出的debug部分重點說明如下:
- login: 變量名,其值為一個字典
- changed:ansible基於此來判斷是否發生了狀態改變
- cmd:被調用的命令
- failed:是否運行失敗
- rc:返回值,0代表正常,非0代表異常
- stderr:如果出現異常,會在這里顯示錯誤輸出
- stderr_lines:按行分割的錯誤輸出
- stdout:如果指令正常運行,則在這里輸出返回結果
- stdout:按行分割的返回結果
需要說明的是,通過register注冊的變量的結果並不是一成不變的,在不確定返回值的情況下,盡量調試看看輸出結果。
關於debug的更多用法說明:
調試模塊,用於在調試中輸出信息
常用參數:
- msg:調試輸出的消息
- var:將某個變量傳遞給debug模塊,debug會直接將其打印輸出
- verbosity:debug的級別
博主聲明:本文的內容來源主要來自譽天教育晏威老師,由本人實驗完成操作驗證,需要的博友請聯系譽天教育(http://www.yutianedu.com/),獲得官方同意或者晏老師(https://www.cnblogs.com/breezey/)本人同意即可轉載,謝謝!