如果您需要根據不同條件執行Ansible任務,那麼您將會受到獎勵。Ansible的when和其他條件語句讓您可以評估條件,例如基於作業系統,或者一個任務是否依賴於前一個任務。
在本教程中,您將學習如何使用Ansible的when和其他條件語句,以便在不搞砸事情的情況下執行任務。
讓我們開始吧!
先決條件
本教程包含實際示例。如果您想跟隨操作,請確保您已準備好以下內容:
- 一個Ansible控制器主機 – 本教程使用安裝在Ubuntu 18.04.5 LTS機器上的Ansible v2.9.24。
- A remote computer to run commands.
- 您需要設置一個清單文件,並且已經配置了一個或多個主機以運行Ansible命令和Playbook。本教程將使用一個名為web的清單組。
在Playbook中使用Ansible的when處理多個任務
在Playbook中有多个任务,如果它们都没有特定的条件执行,可能会很麻烦。让我们从在Ansible Playbook中定义Ansible when
条件开始这个教程,其中包含多个任务。
1. 在Ansible控制器主机上打开终端。
2. 运行以下命令在您的主目录中创建一个目录,并将其命名为您喜欢的任何名称,并导航到该目录中。
在这个例子中,目录名为ansible_when_condition_demo
。该目录将包含您将在Ansible任务中使用的playbook中的when条件。
3. 在您喜欢的代码编辑器中,在~/ansible_when_condition_demo目录中创建一个YAML文件。在这个例子中,该文件被称为my_playbook.yml。复制并粘贴以下YAML playbook内容到my_playbook.yml文件中。
在下面的两个任务(Task-1
和Task-2
)中,when
条件检查每个远程主机所在的操作系统。然后将结果传递给每个任务中的ansible_os_family
占位符变量。
如果ansible_os_family
占位符的值等于RedHat
或Debian
,那么Ansible将执行以下任务之一来安装Apache。
4. 现在运行下面的ansible-playbook
命令,在现有清单文件中定义的远程主机上执行playbook(my_playbook.yml)中定义的任务。
在下面的屏幕截图中,您可以看到:
- 第一个任务返回了一个OK状态,表示该任务不需要进行任何更改。
- 第二个任务返回了skipping状态。当条件不满足时,任务将被跳过。
- 第三个任务返回了一个changed状态,表示远程主机不处于正确的状态(即Apache不存在),并且已被修改以安装Apache。

5. 使用您喜歡的 SSH 客戶端打開 SSH 會話,連接到 Ansible playbook 的目標遠程主機,以驗證 Apache 是否已安裝並運行。
6. 最後,執行以下service
命令來驗證遠程主機上是否已安裝 Apache(status apache2
)。
如下所示,您已在遠程機器上安裝了 Apache 服務。

使用 Ansible 的 when
和循環
之前,您根據 Ansible 的 when
條件執行了 Ansible 任務,例如 ansible_os_family
。但也許您需要檢查在列表中定義的多個參數的條件。如果是這樣,請嘗試在任務中添加一個 loop
。
打開之前創建的 my_playbook.yml 文件(在“在 Playbook 中使用 Ansible when
執行多個任務”下的第三步)。將 my_playbook.yml 文件的內容替換為以下代碼。
代碼中的任務(Task-1
)運行一個 loop
,其中 when
條件檢查項目值是否大於五並返回結果。
現在執行以下命令來執行 playbook,就像之前一樣。
以下是當條件為false時返回的任務返回跳過狀態,而當條件為true時返回的已更改狀態。

when
condition for multiple parameters 使用Ansible的when
和Ansible的facts
也許您想要添加多個條件來執行任務。如果是這樣,請學習如何在when
條件中使用Ansible facts。 Ansible facts允許您添加一個條件語句來根據收集到的事實執行任務,例如您的操作系統、IP地址、連接的文件系統等等。
將my_playbook.yml文件的內容替換為下面的代碼。
在下面的代碼中,當以下任一條件為真時,兩個任務(Task-1
和Task-2
)都只會執行(系統關機):
distribution
和distribtion_major_version
都返回true值。os_family
的值等於CentOS
。
像之前一樣使用下面的命令執行playbook。
請注意,由於您使用的是Ubuntu,所以下面的任務都顯示了跳過狀態。只有在CentOS時才執行該任務。

使用基於已註冊值的Ansible when
語句
有時候,您希望根據播放簿中先前任務的結果來執行或跳過一個任務。例如,您可能希望在先前任務升級後配置一個服務。在這種情況下,使用一個已註冊變量。已註冊變量允許您將先前任務的結果註冊為變量並將其作為下一個任務的輸入使用。
1. 創建一個名為/home/ubuntu/hello的空目錄。
2. 將my_playbook.yml文件的內容替換為下面的代碼,該代碼執行以下操作:
第一個任務(Task-1
)將/etc/hosts
目錄的內容(文件和子目錄)列在內存中,並通過register
命令將該結果保存到contents1
變量中。
第二個任務(Task-2
)將/home/ubuntu/hello目錄的內容(目前為空)列在內存中,並將該列表保存到contents2
變量中。
第三個任務(Task-3
)檢查並打印“目錄為空”消息,如果contents1
或contents2
變量的已註冊結果為空。
contents1
和contents2
變量的stdout
屬性是運行任務命令的結果保存的shell輸出。
3. 最後,使用下面的 ansible-playbook
命令執行 playbook。
如下所示,由於 contents2
變數的註冊結果是空的,第三個任務返回 “目錄是空的” 的訊息。

Ansible when
based on registered values 在 Ansible 角色中使用 Ansible when
在這個最後的例子中,您將學習如何在 Ansible 角色中使用 Ansible when
。Ansible 角色允許您重複使用標準配置並更快地部署。繼續閱讀,了解只有當 Ansible when
條件為真時,任務才會調用 Ansible 角色的方法。
1. 執行以下命令在您的家目錄中創建一個名為 ~/ansible_role_when_demo 的目錄,並將其設置為工作目錄。 ~/ansible_role_when_demo 目錄將保存此示例的演示文件。
2. 接下來,執行以下命令來創建 ~/ansible_role_when_demo/roles 和 ~/ansible_role_when_demo/roles/java/tasks 目錄。
以下是每個目錄的內容:
- ~/ansible_role_when_demo/roles 目錄將包含您需要部署的角色。
預設情況下,Ansible 在 playbook 所在目錄的 roles/ 目錄或 /etc/ansible/roles 目錄中尋找角色。如果您希望將角色存儲在其他路徑,可以在 playbook 中使用
- role:
參數聲明這些路徑。
- ~/ansible_role_when_demo/roles/java/tasks 文件夾將包含您需要部署角色的 main.yml 文件。
現在,在~/ansible_role_when_demo/roles/java/tasks目錄下創建一個名為main.yml的文件,然後將下面的playbook代碼複製並粘貼到main.yml文件中。
下面的playbook在遠程節點上使用apt模塊安裝Java。
4. 創建一個您喜歡的名字的另一個YAML文件,並複製/粘貼下面的代碼。對於此示例,文件名為~/ansible_role_when_demo/java-setup.yml。
下面的代碼將Ansible的role
(java
)部署到僅當遠程用戶為Debian OS時具有管理訪問權限的遠程用戶(ubuntu
)。
5. 執行 tree
命令來驗證所有需要的資料夾和檔案是否存在於 ~/ansible_role_when_demo 目錄中。

6. 最後,使用下面的 ansible-playbook
命令執行 playbook。 ansible-playbook java-setup.yml
下面的任務返回了一個 changed 狀態,表示已成功在遠程節點上安裝了 Java,因為該節點運行的是 Debian 作業系統。 使用 Ansible 角色和
Ansible when
執行 Ansible playbook

Ansible when
with Ansible roles 結論
在本教程中,您學習了使用 Ansible 的不同方式,包括使用 when
和其他條件語句。您還學習了如何應用 Ansible when
條件,從基本任務利用 Ansible facts
到部署 Ansible roles
。
現在,您可以如何在這個新獲得的知識基礎上進一步應用呢?也許可以在應用 Ansible when
條件的同時,使用 Ansible 模板節省配置多個伺服器的時間?