獲取執(zhí)行命令的輸出 --Register
在剛開(kāi)始使用 ansible-playbook 做應(yīng)用程序部署的時(shí)候士聪,因?yàn)樵诓渴鸬倪^(guò)程中有使用到 command 或 shell 模塊執(zhí)行一些自定義的腳本匠襟,而且這些腳本都會(huì)有輸出愧旦,用來(lái)表示是否執(zhí)行正常或失敗恨统。如果像之前自己寫(xiě)腳本做應(yīng)用程序部署的,這很好實(shí)現(xiàn)。但現(xiàn)在是用 Ansible 做掰盘,那么要怎么樣做可以獲取到 ansible playbook 中 command 模塊的輸出呢? Ansible 也提供的解決辦法赞季,這時(shí)我們就可以通過(guò)使用 register 關(guān)鍵字來(lái)實(shí)現(xiàn)愧捕,register 關(guān)鍵字可以存儲(chǔ)指定命令的輸出結(jié)果到一個(gè)自定義的變量中,我們通過(guò)訪問(wèn)這個(gè)自定義變量就可以獲取到命令的輸出結(jié)果申钩。Register 的使用很方便次绘,只需要在 task 聲明 register 關(guān)鍵字,并自定義一個(gè)變量名就可以撒遣。如下:
- name: echo date
command: date
register: date_output
- name: echo date_output
command: echo "30"
when: date_output.stdout.split(' ')[2] == "30"
這里第 1 個(gè) task 是執(zhí)行了一個(gè) date 命令邮偎,register 關(guān)鍵字將 date 命令的輸出存儲(chǔ)到 date_output 變量名。第 2 個(gè) task 對(duì)輸出進(jìn)行分析义黎,并使用 when 對(duì)關(guān)鍵字對(duì)分析后的進(jìn)行判斷禾进,如果匹配,則執(zhí)行這個(gè) task廉涕,不匹配就不執(zhí)行泻云。這里要重點(diǎn)說(shuō)下的,因?yàn)?register 獲取到的輸出內(nèi)容都是字符串狐蜕,而 ansible 又是 python 寫(xiě)的宠纯,你可以使用 python 字符串的方法對(duì)其做處理,比如本文中使用的 split层释,還可以使用 find 方法婆瓜。個(gè)人覺(jué)得,真是非常靈活方便。
register 執(zhí)行結(jié)果 1
這里由于條件匹配廉白,兩個(gè) task 都執(zhí)行了个初。然后把第 2 個(gè) task 中的條件改動(dòng)了下,使其不匹配猴蹂,執(zhí)行結(jié)果如下:
register 執(zhí)行結(jié)果 2
這里第 2 個(gè) task 條件不匹配勃黍,skipping 了。
Delegate_to( 任務(wù)委派功能 )
場(chǎng)景介紹:在對(duì)一組服務(wù)器 server_group1 執(zhí)行操作過(guò)程中晕讲,需要在另外一臺(tái)機(jī)器 A 上執(zhí)行一個(gè)操作覆获,比如在 A 服務(wù)器上添加一條 hosts 記錄,這些操作必須要在一個(gè) playbook 聯(lián)動(dòng)完成瓢省。也就是是說(shuō) A 服務(wù)器這個(gè)操作與 server_group1 組上的服務(wù)器有依賴(lài)關(guān)系弄息。Ansible 默認(rèn)只會(huì)在定義好的一組服務(wù)器上執(zhí)行相同的操作,這個(gè)特性對(duì)于執(zhí)行批處理是非常有用的勤婚。但如果在這過(guò)程中需要同時(shí)對(duì)另外 1 臺(tái)機(jī)器執(zhí)行操作時(shí)摹量,就需要用到 Ansible 的任務(wù)委派功能(delegate_to)。使用 delegate_to 關(guān)鍵字可以委派任務(wù)到指定的機(jī)器上運(yùn)行馒胆。在 playbook 的操作如下:
- name: add host record
shell: 'echo "192.168.1.100 test.xyz.com" >> /etc/hosts'
- name: add host record to center server
shell: 'echo "192.168.1.100 test.xyz.com " >> /etc/hosts'
delegate_to: 192.168.1.1
任務(wù)委派功能還可以用于以下場(chǎng)景:
- 在部署之前將一個(gè)主機(jī)從一個(gè)負(fù)載均衡集群中刪除缨称。
- 當(dāng)你要對(duì)一個(gè)主機(jī)做改變之前去掉相應(yīng) dns 的記錄
- 當(dāng)在一個(gè)存儲(chǔ)設(shè)備上創(chuàng)建 iscsi 卷的時(shí)候
- 當(dāng)使用外的主機(jī)來(lái)檢測(cè)網(wǎng)絡(luò)出口是否正常的時(shí)候
本地操作功能 --local_action
Ansible 默認(rèn)只會(huì)對(duì)控制機(jī)器執(zhí)行操作,但如果在這個(gè)過(guò)程中需要在 Ansible 本機(jī)執(zhí)行操作呢祝迂?細(xì)心的讀者可能已經(jīng)想到了睦尽,可以使用 delegate_to( 任務(wù)委派 ) 功能呀。沒(méi)錯(cuò)型雳,是可以使用任務(wù)委派功能實(shí)現(xiàn)当凡。不過(guò)除了任務(wù)委派之外,還可以使用另外一外功能實(shí)現(xiàn)纠俭,這就是 local_action 關(guān)鍵字沿量。
- name: add host record to center server
local_action: shell 'echo "192.168.1.100 test.xyz.com " >> /etc/hosts'
當(dāng)然您也可以使用 connection:local 方法,如下:
- name: add host record to center server
shell: 'echo "192.168.1.100 test.xyz.com " >> /etc/hosts'
connection: local
這兩個(gè)操作結(jié)果是一樣的冤荆。
Check 模式
當(dāng)以— check 參數(shù)來(lái)運(yùn)行 ansible-playbook 時(shí)朴则,將不會(huì)對(duì)遠(yuǎn)程的系統(tǒng)作出任何修改。相對(duì)的钓简,任何帶有檢測(cè)功能的模塊只要支持‘檢測(cè)模式’將會(huì)報(bào)告它們會(huì)做出什么改變而不是直接進(jìn)行改變乌妒。其他不支持檢測(cè)模式的模塊將即不響應(yīng)也不提出相應(yīng)的報(bào)告(事實(shí)上幾乎所有主要核心模塊都是支持‘檢測(cè)模式’)。檢測(cè)模式只是一種模擬涌庭。如果你的 playbook 是以先前命令的執(zhí)行結(jié)果作為條件的話(huà)芥被,那它可能作用就不明顯了欧宜。但是在正式運(yùn)行前坐榆,使用 check 模式做個(gè)語(yǔ)法檢查也是不錯(cuò)的。
選擇性執(zhí)行 task-- Tag(標(biāo)簽)
您可能因?yàn)槟承┰蛉呷祝瑫?huì)創(chuàng)建一個(gè)很大型的 playbook席镀,但是你可能只想想運(yùn)行其中特定部分的配置而無(wú)需要運(yùn)行整個(gè) playbook 匹中。那么這時(shí)你可能需要用到 tag 功能。示例如下:
- name: yun install package
yum: name={{ item }} state=installed
with_items:
- httpd
- memcached
tags:
- packages
- name: configuration modity
template: src=templates/src.j2 dest=/etc/foo.conf
tags:
- configuration
如果你只想運(yùn)行 playbook 中的”configuration”和”packages”豪诲,你可以這樣做
ansible-playbook example.yml – tags “configuration,packages”
如果你只想執(zhí)行 playbook 中某個(gè)特定任務(wù)之外的所有任務(wù)顶捷,你可以這樣做:
ansible-playbook example.yml – skip-tags “configuration”
tag 特性是一個(gè)不錯(cuò)的功能,但如果真的是要維護(hù)一個(gè)大型的 playbook屎篱,還是建議將 playbook 按功能或應(yīng)用拆分成多個(gè) playbook服赎,然后再在主 playbook include 其他子 playbook,這樣即既利于維護(hù)也方便管理
錯(cuò)誤處理
Ansible 默認(rèn)會(huì)檢查命令和模塊的返回狀態(tài)交播,并進(jìn)行相應(yīng)的錯(cuò)誤處理重虑,默認(rèn)是遇到錯(cuò)誤就中斷 playbook 的執(zhí)行,這些默認(rèn)行為都是可以改變的秦士。
忽略錯(cuò)誤
command 和 shell 模塊執(zhí)行的命令如果返回非零狀態(tài)碼則 ansible 判定這 2 個(gè)模塊執(zhí)行失敗缺厉,可以通過(guò) ignore_errors 忽略返回狀態(tài)碼(前提是要確定這 command 與 shell 執(zhí)行錯(cuò)誤不會(huì)影響后面 task 的執(zhí)行)。如下:
- name: this will not be counted as a failure
command: /bin/false
ignore_errors: yes
自定義錯(cuò)誤判定條件
命令不依賴(lài)返回狀態(tài)碼來(lái)判定是否執(zhí)行失敗隧土,而是要查看命令返回內(nèi)容來(lái)決定提针,比如返回內(nèi)容中包括 failed 字符串,則判定為失敗曹傀。示例如下:
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
failed_when: "'FAILED' in command_result.stderr"
ansible 會(huì)自動(dòng)判斷模塊執(zhí)行狀態(tài)辐脖,command、shell 及其它模塊如果修改了遠(yuǎn)程主機(jī)狀態(tài)則被判定為 change 狀態(tài)皆愉,不過(guò)也可以自己決定達(dá)到 changed 狀態(tài)的條件揖曾,示例如下:
- name: copy in nginx conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: validate nginx conf
shell: "/data/app/nginx/sbin/nginx -t"
register: command_result
changed_when: command_result.stdout.find('successful')
命令返回中有“successful”字符串,則為 changed 狀態(tài)亥啦,下面這個(gè)設(shè)定將永遠(yuǎn)也不會(huì)達(dá)到 changed 狀態(tài)炭剪。
- name: validate nginx conf
shell: "/data/app/nginx/sbin/nginx -t"
changed_when: false