前文中,我們使用”when”關(guān)鍵字對(duì)條件進(jìn)行判斷,如果條件成立,則執(zhí)行對(duì)應(yīng)的任務(wù),但是,細(xì)心如你一定已經(jīng)發(fā)現(xiàn)了,當(dāng)條件成立時(shí),我們只能執(zhí)行一個(gè)任務(wù),如果我們想要在條件成立時(shí),執(zhí)行三個(gè)任務(wù),該怎么辦呢?難道我們要在這三個(gè)任務(wù)的每個(gè)任務(wù)中都加入相同的條件判斷么?這種方法也太麻煩了,顯然應(yīng)該有更好的方法,沒(méi)錯(cuò),我們可以借助”block”解決這個(gè)小問(wèn)題。
---
- hosts: test70
remote_user: root
tasks:
- debug:
msg: "task1 not in block"
- block:
- debug:
msg: "task2 in block1"
- debug:
msg: "task3 in block1"
when: 2 > 1

上例中一共包含三個(gè)任務(wù),第一個(gè)任務(wù)使用debug模塊輸出了 “task1 not in block”這句話,在第一個(gè)任務(wù)之后,我們定義了一個(gè)block,這個(gè)block中包含兩個(gè)任務(wù),兩個(gè)debug任務(wù)分別輸出各自的信息,上例的when關(guān)鍵字與block關(guān)鍵字對(duì)齊,表示when關(guān)鍵字的條件是針對(duì)block的,當(dāng)when對(duì)應(yīng)的條件成立,則執(zhí)行block中的兩個(gè)任務(wù)。
block除了能夠與when結(jié)合在一起使用,還有一個(gè)很有用的功能,就是”錯(cuò)誤處理”功能。
“錯(cuò)誤處理”功能就是當(dāng)某任務(wù)出錯(cuò)時(shí),執(zhí)行指定的其他任務(wù),打個(gè)比方,我們想要在A任務(wù)執(zhí)行失敗時(shí)執(zhí)行B任務(wù),如果A任務(wù)執(zhí)行成功,則無(wú)需執(zhí)行B任務(wù),實(shí)現(xiàn)這個(gè)功能,就能夠使用block,當(dāng)然,我們還有一些別的方法,也可以實(shí)現(xiàn)類似的功能,比如前文中提到的jinja2的tests,有個(gè)一名為failed的test,借助failed也可以實(shí)現(xiàn)類似的功能,此處我們先回顧一下failed的用法,然后對(duì)比著failed的示例,介紹block的用法,使用failed完成上述錯(cuò)誤處理的示例代碼如下:
---
- hosts: test70
remote_user: root
tasks:
- shell: 'ls /ooo'
register: return_value
ignore_errors: true
- debug:
msg: "I cought an error"
when: return_value is failed

如上例所示,我在shell任務(wù)中執(zhí)行了’ls /ooo’命令,而test70主機(jī)中并不存在/ooo這個(gè)路徑,所以shell模塊執(zhí)行時(shí)一定會(huì)出錯(cuò),我將shell任務(wù)執(zhí)行的返回值注冊(cè)到了return_value變量中,然后使用”is failed”進(jìn)行判斷,如果條件成立,代表shell任務(wù)執(zhí)行出錯(cuò),則執(zhí)行debug任務(wù),輸出對(duì)應(yīng)的信息,上述示例就能實(shí)現(xiàn)我們剛才所要求的功能,如果用block來(lái)實(shí)現(xiàn),該怎樣編寫(xiě)playbook呢?來(lái)看一個(gè)小示例,如下:
---
- hosts: test70
remote_user: root
tasks:
- block:
- shell: 'ls /ooo'
rescue:
- debug:
msg: 'I caught an error'
如上例所示,我定義了一個(gè)block,這個(gè)block中有一個(gè)任務(wù),這個(gè)任務(wù)在目標(biāo)主機(jī)中執(zhí)行了’ls /ooo’命令,除了block關(guān)鍵字,還有另外一個(gè)關(guān)鍵字rescue,rescue關(guān)鍵字與block關(guān)鍵字對(duì)齊,rescue的字面意思為”救援”,表示當(dāng)block中的任務(wù)執(zhí)行失敗時(shí),會(huì)執(zhí)行rescue中的任務(wù)進(jìn)行補(bǔ)救,當(dāng)然,在rescue中定義什么任務(wù),是由你決定的,上述示例主要是為了說(shuō)明,當(dāng)block中的任務(wù)出錯(cuò)時(shí),會(huì)執(zhí)行rescue中的任務(wù),當(dāng)block中的任務(wù)順利執(zhí)行時(shí),則不會(huì)執(zhí)行rescue中的任務(wù)。
你可能會(huì)問(wèn),使用block的方法完成”錯(cuò)誤處理”的功能,似乎與使用failed的方法并沒(méi)有什么不同,除了代碼似乎”精簡(jiǎn)”了一點(diǎn),block還有其他優(yōu)勢(shì)么?其實(shí),使用block的方式還是有一定優(yōu)勢(shì)的,當(dāng)block中有多個(gè)任務(wù)時(shí),這種優(yōu)勢(shì)就比較明顯了,我們來(lái)看一個(gè)小示例,如下
---
- hosts: test70
remote_user: root
tasks:
- block:
- shell: 'ls /opt'
- shell: 'ls /testdir'
- shell: 'ls /c'
rescue:
- debug:
msg: 'I caught an error'
如上例所示,block中有三個(gè)任務(wù),這三個(gè)任務(wù)中的任何一個(gè)任務(wù)出錯(cuò),都會(huì)執(zhí)行rescue中的任務(wù),所以通常,我們會(huì)使用block和rescue結(jié)合,完成”錯(cuò)誤捕捉,報(bào)出異常”的功能,其實(shí),不僅block中可以有多個(gè)任務(wù),rescue中也可以定義多個(gè)任務(wù),當(dāng)block中的任何一個(gè)任務(wù)出錯(cuò)時(shí),會(huì)按照順序執(zhí)行rescue中的任務(wù)。
我們還能夠再加入always關(guān)鍵字,加入always關(guān)鍵字以后,無(wú)論block中的任務(wù)執(zhí)行成功還是失敗,always中的任務(wù)都會(huì)被執(zhí)行,示例如下:
---
- hosts: test70
remote_user: root
tasks:
- block:
- debug:
msg: 'I execute normally'
- command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing'
rescue:
- debug:
msg: 'I caught an error'
- command: /bin/false
- debug:
msg: 'I also never execute'
always:
- debug:
msg: "This always executes"
如上例所示,block中有多個(gè)任務(wù),rescue中也有多個(gè)任務(wù),上例中故意執(zhí)行”/bin/false”命令,模擬任務(wù)出錯(cuò)的情況,當(dāng)block中的’/bin/false’執(zhí)行后,其后的debug任務(wù)將不會(huì)被執(zhí)行,因?yàn)椤?bin/false’模擬出錯(cuò),出錯(cuò)后直接執(zhí)行rescue中的任務(wù),在執(zhí)行rescue中的任務(wù)時(shí),會(huì)先輸出 ‘I caught an error’,然后又在rescue中使用’/bin/false’模擬出錯(cuò)的情況,出錯(cuò)后之后的debug任務(wù)不會(huì)被執(zhí)行,直接執(zhí)行always中的任務(wù),always中的任務(wù)一定會(huì)被執(zhí)行,無(wú)論block中的任務(wù)是否出錯(cuò)。
