ansible循環+判斷(with,loop,when,if,for)

一、文檔核心定位

本文檔聚焦Ansible自動化運維中的兩大核心功能——循環判斷,通過“功能說明+完整Playbook代碼”的形式,覆蓋循環迭代場景(列表、字典、文件等)、數據處理過濾器(字符串、數字、加密等)、條件判斷邏輯(變量、任務結果、路徑等)及錯誤處理方案,所有代碼均針對Linux環境設計,可直接在Ansible控制端編輯執行。

二、Ansible循環:批量執行重復任務

Ansible循環通過with_*系列關鍵字或loop(配合過濾器)實現,核心是用{{ item }}指代迭代對象,適配不同批量操作場景,以下為所有循環類型的詳細拆解。

(一)with_items:迭代列表(最常用場景)

功能定義

遍歷列表中的元素,將每個元素作為{{ item }}代入任務,實現“一次定義,多次執行”,典型場景為批量安裝軟件包、創建多個文件或用戶。

應用場景

在Linux受控節點(如node1)批量安裝httpd(網頁服務)、samba(文件共享服務)、samba-client(samba客戶端),需先配置本地yum源(依賴光盤掛載)。

完整代碼與逐行說明
# 編輯Playbook文件:vim b.yml
---
- name: install packages  # Play名稱:明確任務目標(安裝軟件包)hosts: node1  # 目標受控節點:指定任務在node1上執行tasks:  # 任務列表:包含依賴配置與核心安裝任務# 任務1:配置BaseOS本地yum源(為安裝軟件提供包來源)- name: yum_repo1  # 任務名:區分不同yum源配置yum_repository:  # 模塊:用于管理yum倉庫配置file: server  # 配置文件名:最終生成/etc/yum.repos.d/server.reponame: baseos  # 倉庫標識名:唯一識別該倉庫description: rhel8  # 倉庫描述:說明倉庫用途(RHEL8系統源)baseurl: file:///mnt/BaseOS  # 包源路徑:本地光盤掛載后的BaseOS目錄enabled: yes  # 啟用倉庫:允許通過該倉庫安裝軟件gpgcheck: no  # 關閉GPG校驗:本地源無需校驗包完整性# 任務2:配置AppStream本地yum源(補充軟件包來源)- name: yum_repo2yum_repository:file: server  # 與BaseOS共用一個配置文件name: appstream  # 倉庫標識名:與BaseOS區分description: appstream  # 倉庫描述:RHEL8應用流源baseurl: file:///mnt/AppStream  # 包源路徑:光盤掛載后的AppStream目錄enabled: yesgpgcheck: no# 任務3:掛載光盤(為yum源提供本地文件支持)- name: mount cdrom  # 任務名:掛載光盤mount:  # 模塊:用于管理文件系統掛載src: /dev/cdrom  # 源設備:Linux中光盤的設備文件path: /mnt  # 掛載點:將光盤掛載到/mnt目錄fstype: iso9660  # 文件系統類型:ISO鏡像固定格式state: mounted  # 掛載狀態:確保光盤已掛載(若未掛載則自動掛載)# 任務4:核心循環安裝軟件(with_items迭代列表)- name: install pks  # 任務名:安裝目標軟件包yum:  # 模塊:用于管理RPM軟件包name: "{{ item }}"  # 軟件名:{{ item }}依次取列表中的軟件名state: present  # 安裝狀態:確保軟件已安裝(若未安裝則自動安裝)with_items:  # 迭代列表:需安裝的軟件包集合- httpd- samba- samba-client
執行與驗證
  1. 執行命令:ansible-playbook b.yml
  2. 驗證方式:在node1上執行rpm -qa | grep -E "httpd|samba",確認3個軟件均已安裝。

(二)with_dict:迭代字典(鍵值對關聯場景)

功能定義

遍歷字典的“鍵-值”對,通過item.key調用字典的鍵(如配置項名稱),item.value調用對應的值(如配置項內容),適用于批量處理關聯數據(如網絡配置、服務端口映射)。

應用場景

打印網絡配置中的address(IP地址)、netmask(子網掩碼)、gateway(網關)的鍵值對,驗證字典迭代邏輯。

完整代碼與說明
# 編輯Playbook文件:vim c.yml
---
- name: test  # Play名稱:測試字典迭代hosts: node1tasks:- name: debug  # 任務名:輸出調試信息debug:  # 模塊:用于輸出變量或文本信息msg: "{{ item.key }} & {{ item.value }}"  # 輸出格式:鍵 & 值with_dict:  # 迭代字典:網絡配置鍵值對address: 1  # 鍵:address,值:1(示例值,可替換為實際IP如192.168.1.10)netmask: 2  # 鍵:netmask,值:2(示例值,可替換為255.255.255.0)gateway: 3  # 鍵:gateway,值:3(示例值,可替換為192.168.1.1)
執行結果示例
TASK [debug] *****************************************************************
ok: [node1] => (item={'key': 'address', 'value': 1}) => {"msg": "address & 1"
}
ok: [node1] => (item={'key': 'netmask', 'value': 2}) => {"msg": "netmask & 2"
}
ok: [node1] => (item={'key': 'gateway', 'value': 3}) => {"msg": "gateway & 3"
}

(三)with_fileglob:迭代文件(批量文件操作)

功能定義

匹配Ansible控制端指定路徑下的文件(支持通配符*),批量處理文件操作(如拷貝、刪除),需注意:僅識別控制端文件,不識別受控端文件。

應用場景

將控制端/tmp目錄下所有.sh(Shell腳本)和.py(Python腳本)文件,批量拷貝到受控端node1的/tmp目錄。

完整代碼與說明
# 編輯Playbook文件:vim d.yml
---
- name: test  # Play名稱:測試文件迭代拷貝hosts: node1tasks:- name: cp file  # 任務名:拷貝文件copy:  # 模塊:用于文件拷貝(控制端→受控端)src: "{{ item }}"  # 源文件路徑:{{ item }}依次取匹配的控制端文件dest: /tmp/  # 目標路徑:受控端的/tmp目錄(保持原文件名)with_fileglob:  # 控制端文件匹配規則- /tmp/*.sh  # 匹配控制端/tmp下所有.sh后綴的文件- /tmp/*.py  # 匹配控制端/tmp下所有.py后綴的文件

(四)with_lines:迭代命令輸出行(基于命令結果操作)

功能定義

執行Linux命令(在控制端執行),將命令輸出按“行”拆分,每一行作為{{ item }}代入任務,適用于基于命令結果的批量操作(如拷貝命令找到的特定文件)。

應用場景

查找控制端/etc/ansible目錄下所有.yml(Ansible Playbook)文件,批量拷貝到受控端node1的/tmp目錄。

完整代碼與說明
# 編輯Playbook文件:vim e.yml
---
- name: test  # Play名稱:測試命令輸出迭代hosts: node1tasks:- name: cp file  # 任務名:拷貝.yml文件copy:src: "{{ item }}"  # 源文件路徑:find命令輸出的每一行(單個.yml文件路徑)dest: /tmp/with_lines:  # 執行命令并迭代輸出行- find /etc/ansible -name "*.yml"  # 命令:查找ansible目錄下所有.yml文件

(五)with_nested:嵌套迭代(多列表組合場景)

功能定義

實現多列表的“笛卡爾積”迭代,即第一個列表的每個元素與第二個列表的所有元素逐一組合,通過item[0]調用第一個列表元素,item[1]調用第二個列表元素。

應用場景

將列表[a, b](如服務名稱)與列表[1, 2, 3](如實例編號)組合,生成a&1a&2a&3b&1b&2b&3等組合,用于批量生成服務實例名稱。

完整代碼與說明
# 編輯Playbook文件:vim f.yml
---
- name: test  # Play名稱:測試嵌套迭代hosts: node1tasks:- name: debug  # 任務名:輸出組合結果debug:msg: "{{ item[0] }} & {{ item[1] }}"  # 輸出格式:第一個列表元素 & 第二個列表元素with_nested:  # 嵌套迭代的兩個列表- [a, b]  # 第一個列表:基礎元素- [1, 2, 3]  # 第二個列表:組合元素

(六)with_sequence:排序列(有序數字生成)

功能定義

生成指定范圍、步長的有序數字序列,支持3個核心參數:

  • start:序列起始值(默認從0開始)
  • end:序列結束值(必填)
  • stride:序列步長(默認1,即連續數字)
應用場景

生成1-5的連續數字序列(步長1),用于批量創建帶編號的資源(如文件file1-file5、用戶user1-user5)。

完整代碼與說明
# 編輯Playbook文件:vim g.yml
---
- name: test  # Play名稱:測試有序序列生成hosts: node1tasks:- name: debug  # 任務名:輸出序列數字debug:msg: "{{ item }}"  # 輸出每個序列數字with_sequence:  # 序列參數配置start=1  # 起始值:1end=5    # 結束值:5stride=1 # 步長:1(生成1、2、3、4、5)

(七)with_random_choice:隨機取值(隨機操作場景)

功能定義

從指定列表中隨機選擇一個元素執行任務,每次運行Playbook的結果可能不同,適用于需要隨機化的場景(如隨機選擇測試節點、隨機生成測試數據)。

應用場景

從列表[1, 2, a, b, c]中隨機選擇一個元素輸出,驗證隨機迭代邏輯。

完整代碼與說明
# 編輯Playbook文件:vim h.yml
---
- name: test  # Play名稱:測試隨機取值hosts: node1tasks:- name: debug  # 任務名:輸出隨機元素debug:msg: "{{ item }}"  # 輸出隨機選中的元素with_random_choice:  # 隨機選擇的列表- 1- 2- a- b- c

(八)Loop與過濾器:數據處理增強

功能定義

loop是Ansible推薦的新版循環方式,需配合過濾器實現數據處理(如字符串轉換、數字計算、密碼加密),過濾器通過|調用,可直接作用于變量或迭代結果。

1. 常用字符串過濾器(處理文本數據)
功能說明
過濾器作用示例輸出結果
upper字符串轉全大寫`“abc123ABC 666”upper`
lower字符串轉全小寫`“abc123ABC 666”lower`
trim去除首尾空格`" abc "trim`
length計算字符串長度(含空格)`“abc123ABC 666”length`
完整代碼
---
- name: test  # Play名稱:測試字符串過濾器hosts: node1vars:  # 定義測試變量testvar: "abc123ABC 666"  # 含大小寫、數字、空格的字符串testvar1: " abc "  # 含首尾空格的字符串tasks:- name: debug1  # 測試upper過濾器debug:msg: "{{ testvar | upper }}"- name: debug2  # 測試lower過濾器debug:msg: "{{ testvar | lower }}"- name: debug3  # 測試trim過濾器debug:msg: "{{ testvar1 | trim }}"- name: debug4  # 測試length過濾器debug:msg: "{{ testvar | length }}"
2. 補充字符串過濾器
完整代碼與說明
# 編輯文件:vim filterstr.yml
---
- name: 過濾器  # Play名稱:補充字符串過濾器測試hosts: servera  # 目標節點:servera(可替換為node1)vars:testvar: "abc123ABC 666"testvar1: "  abc  "testvar2: "123456789"testvar3: "1a2b,@#$%^&"  # 含特殊字符的字符串tasks:- name: 將字符串轉換成純大寫debug: msg="{{ testvar | upper }}"- name: 將字符串轉換成純小寫debug: msg="{{ testvar | lower }}"- name: 將字符串首字母大寫,之后的所有字母純小寫(capitalize)debug: msg="{{ testvar | capitalize }}"  # 輸出:Abc123abc 666- name: 返回字符串的第一個字符(first)debug: msg="{{ testvar | first }}"  # 輸出:a- name: 返回字符串的最后一個字符(last)debug: msg="{{ testvar | last }}"  # 輸出:6- name: 將字符串開頭和結尾的空格去除(trim)debug: msg="{{ testvar1 | trim }}"- name: 將字符串居中,總長度30,兩邊用空格補齊(center)debug: msg="{{ testvar1 | center(width=30) }}"  # 輸出:中間為abc,兩邊共27個空格- name: 返回字符串長度(length,與count等效)debug: msg="{{ testvar2 | length }}"  # 輸出:9- name: 將字符串轉換成列表,每個字符為元素(list)debug: msg="{{ testvar3 | list }}"  # 輸出:['1','a','2','b',',','@','#','$','%','^','&']- name: 將字符串轉列表并隨機打亂(shuffle,“洗牌”效果)debug: msg="{{ testvar3 | shuffle }}"  # 輸出:隨機排序的字符列表
3. 數字操作過濾器(處理數值數據)
[root@foundation0 ansible]# cat filterdata.yml 
---
- name: this playbookhosts: serveravars:testvar4: -1tasks:- name: 轉int并計算(字符串與數字不可直接計算)debug: msg="{{ 8+('8' | int) }}"- name: 轉int,無法轉換返回默認值6debug: msg="{{ 'a' | int(default=6) }}"- name: 轉floatdebug: msg="{{ '8' | float }}"- name: 轉float,無法轉換返回8.88debug: msg="{{ 'a' | float(8.88) }}"- name: 取絕對值(abs)debug: msg="{{ testvar4 | abs }}"- name: 四舍五入(round 四舍五入偶數)debug: msg="{{ 12.5 | round }}" ##輸出為12- name: 保留5位小數(round(5))debug: msg="{{ 3.1415926 | round(5) }}"- name: 0-100隨機數(random)debug: msg="{{ 100 | random }}"- name: 5-10隨機數(start=5)debug: msg="{{ 10 | random(start=5) }}"- name: 5-15隨機數,步長3(step=3)debug: msg="{{ 15 | random(start=5,step=3) }}"- name: 0-15隨機數,5的倍數(step=5)debug: msg="{{ 15 | random(step=5) }}"
功能說明
過濾器作用示例輸出結果
int轉整數,無法轉換時返回默認值(默認0)`“8”int“a”
float轉浮點型,無法轉換時返回默認值(默認0.0)`“8”float“a”
abs取絕對值`-1abs`
round四舍五入,可指定小數位數`12.5round3.1415926
random生成隨機數,支持
4. 文件 / 目錄類過濾器(含加密)
  • 代碼
[root@foundation0 ansible]# cat filterfile.yml 
---
- name: 文件或目錄類的過濾器hosts: serveratasks:- name: sha1哈希debug: msg="{{ '123456' | hash('sha1') }}"- name: md5哈希debug: msg="{{ '123456' | hash('md5') }}"- name: 校驗和(與md5一致)debug: msg="{{ '123456' | checksum }}"- name: sha256哈希(隨機鹽)debug: msg="{{ '123456' | password_hash('sha256') }}"- name: sha256哈希(指定鹽mysalt)debug: msg="{{ '123456' | password_hash('sha256','mysalt') }}"- name: sha512哈希(隨機鹽)debug: msg="{{ '123123' | password_hash('sha512') }}"- name: sha512哈希(指定鹽ebzL.U5cjaHe55KK)debug: msg="{{ '123123' | password_hash('sha512','ebzL.U5cjaHe55KK') }}"
5. 加密算法應用(創建帶哈希密碼的用戶)
  • 代碼
---
- name: create userhosts: node1tasks:- name: create chenyuuser:name: chenyupassword: "{{'redhat' | password_hash('sha512')}}"
  • 說明:創建用戶chenyu,密碼redhat用 SHA512 哈希加密存儲。

二、Ansible判斷

通過when關鍵字實現條件執行,支持變量、任務結果、路徑等多維度判斷,核心運算符:==!=><>=<=andornotisin

(一)判斷變量的tests

  • 功能:用defined(已定義)、undefined(未定義)、none(已定義為空)判斷變量狀態。
  • 代碼
Vim test.yml
---
- name: testhosts: node1vars:aa: 11cc:tasks:- name: debug1(aa已定義)debug: msg:a when: aa is defined- name: debug2(bb未定義)debug: msg: ab when: bb is undefined- name: debug3(cc為空)debug: msg: abc when: cc is none

(二)判斷執行結果的tests

  • 功能:用success(成功)、failed(失敗)、changed(狀態變更)、skipped(跳過)判斷任務結果,需先register注冊結果。
  • 代碼
Vim test2.yml
---
- name: testhosts: node1vars:aa: 11tasks:- name: shell(aa==11時執行ls /mnt,注冊結果到dd)shell: cmd: ls /mnt  when: aa == 11 register: dd- name: debug1(任務成功)debug: msg: chenyu success when: dd is success- name: debug2(任務失敗)debug: msg: chenyu failed when: dd is failed- name: debug3(任務變更)debug: msg: chenyu changed when: dd is changed- name: debug4(任務跳過)debug: msg: chenyu skip when: dd is skip

(三)判斷路徑的tests

  • 功能:用file(文件)、directory(目錄)、link(軟鏈接)、mount(掛載點)、exists(存在)判斷路徑狀態,僅針對控制端路徑
  • 代碼
vim test.yml
---
- name: testhosts: node1vars:a1: /test/file1a2: /test/a3: /test/softlinkaa4: /test/hardlinkaa5: /boot/tasks:- name: debug1(a1是文件)debug: msg=this is file when: a1 is file- name: debug2(a2是目錄)debug: msg="this is directory" when: a2 is directory- name: debug3(a3是軟鏈接)debug: msg="this is softlink" when: a3 is link- name: debug4(a4是硬鏈接)debug: msg="this is hardlink" when: a4 is link- name: debug5(a5是掛載點)debug: msg="this is mount directory" when: a5 is mount- name: debug6(a1存在)debug: msg="this is exists" when: a1 is exists

(四)判斷字符串的tests

  • 功能:用lower(字母全小寫)、upper(字母全大寫)判斷字符串大小寫(數字不影響)。
  • 代碼
vim test.yml
---
- name: testhosts: node1vars:a1: abca2: ABCa3: a1btasks:- name: debug1(a1全小寫)debug: msg=this string is all lower when: a1 is lower- name: debug2(a2全大寫)debug: msg=this string is all upper when: a2 is upper- name: debug3(a3字母全小寫)debug: msg=chenyu when: a3 is lower

(五)判斷數據類型的tests

  • 功能:用string(字符串)、number(數字)判斷數據類型。
  • 代碼
vim test.yml
---
- name: testhosts: node1vars:a1: 1a2: "1"a3: atasks:- name: debug1(a1是數字)debug: msg=this is number when: a1 is number- name: debug2(a2是字符串)debug: msg=this is string when: a2 is string- name: debug3(a3是字符串)debug: msg=this is string when: a3 is string

(六)block/rescue/always:限制性塊(錯誤處理)

  • 功能block執行正常任務,失敗則執行rescue,無論成功/失敗都執行always
  • 應用場景:創建邏輯卷,失敗則用備用大小,最后統一格式化;卷組不存在則提示。
  • 前提:node1卷組research為2G,node2為1G(需先通過vg.yml創建)。
    1. 創建卷組的vg.yml代碼:
Vim vg.yml
---
- name: create vg for node1hosts: node1tasks:- name: create partitionparted:device: /dev/sdbnumber: 1part_type: primarypart_start: 10MiBpart_end: 2058MiBstate: present- name: create vg researchlvg: vg=research pvs=/

Ansible邏輯卷配置與錯誤處理例題整理與詳細說明

一、核心例題:邏輯卷(LV)配置與錯誤處理實戰

(一)題目完整需求

創建名為/etc/ansible/lv.yml的Playbook,在所有受管節點執行以下任務:

  1. 創建符合要求的邏輯卷:
    • 位于research卷組中
    • 名稱為data
    • 大小為1500MiB
  2. 使用ext4文件系統格式化該邏輯卷
  3. 錯誤處理:
    • 若無法創建1500MiB大小的邏輯卷,顯示錯誤消息Could not create logical volume of that size,并改為創建800MiB大小
    • research卷組不存在,顯示錯誤消息Volume group does not exist
  4. 不要掛載該邏輯卷

(二)前提準備:卷組(VG)創建

1. 環境準備
  • node1node2上各添加一塊硬盤(假設為/dev/sdb
  • node1research卷組大小為2G
  • node2research卷組大小為1G(用于模擬"無法創建1500MiB邏輯卷"的場景)
2. 卷組創建Playbook(vg.yml
---
# 為node1創建2G的research卷組
- name: create vg for node1hosts: node1tasks:# 步驟1:在/dev/sdb上創建主分區(2048MiB,約2G)- name: create partitionparted:device: /dev/sdb          # 目標硬盤number: 1                 # 分區編號part_type: primary        # 主分區part_start: 10MiB         # 分區起始位置(跳過前10MiB)part_end: 2058MiB         # 分區結束位置(10+2048=2058MiB)state: present            # 確保分區存在# 步驟2:基于/dev/sdb1創建卷組research- name: create vg researchlvg:vg: research              # 卷組名稱pvs: /dev/sdb1            # 使用的物理卷# 為node2創建1G的research卷組
- name: create vg for node2hosts: node2tasks:# 步驟1:在/dev/sdb上創建主分區(1024MiB,約1G)- name: create partition for node2parted:device: /dev/sdbnumber: 1part_type: primarypart_start: 10MiBpart_end: 1034MiB         # 10+1024=1034MiBstate: present# 步驟2:基于/dev/sdb1創建卷組research- name: create vg research for node2lvg:vg: researchpvs: /dev/sdb1
3. 執行卷組創建
ansible-playbook vg.yml

(三)邏輯卷配置Playbook(lv.yml)實現

1. 完整代碼
---
- name: create lvm (邏輯卷配置與錯誤處理)hosts: node1,node2  # 在所有受管節點執行tasks:# 任務1:當research卷組存在時,創建邏輯卷并處理錯誤- name: create lv (卷組存在時執行)block:  # 正常執行的任務塊# 子任務1:嘗試創建1500MiB的邏輯卷- name: create lvm 1500Mlvol:vg: research  # 卷組名稱lv: data      # 邏輯卷名稱size: 1500M   # 邏輯卷大小rescue:  # block執行失敗時觸發(如空間不足)# 子任務1:輸出錯誤消息- name: output fail messagedebug:msg: Could not create logical volume of that size  # 錯誤提示# 子任務2:創建800MiB的備用邏輯卷- name: create lvm 800Mlvol:vg: researchlv: datasize: 800Malways:  # 無論block/rescue是否成功,都執行(格式化操作)# 子任務1:用ext4格式化邏輯卷- name: format lvmfilesystem:fstype: ext4               # 文件系統類型dev: /dev/research/data    # 邏輯卷設備路徑# 條件:僅當research卷組存在時,執行上述block-rescue-alwayswhen: "'research' in ansible_facts.lvm.vgs"  # 或使用"ansible_lvm.vgs"# 任務2:當research卷組不存在時,輸出錯誤消息- name: search not exists (卷組不存在時執行)debug:msg: Volume group does not exist  # 錯誤提示# 條件:僅當research卷組不存在時執行when: "'research' not in ansible_facts.lvm.vgs"  # 或使用"ansible_lvm.vgs"
2. 關鍵語法與邏輯說明
(1)block/rescue/always結構
  • block:包含正常情況下需要執行的任務(嘗試創建1500MiB邏輯卷)
  • rescue:當block中的任何任務失敗時觸發(如node2的卷組只有1G,無法創建1500MiB邏輯卷),執行錯誤處理(輸出消息+創建800MiB邏輯卷)
  • always:無論block成功還是rescue觸發,都會執行的任務(格式化邏輯卷,確保創建后必格式化)
(2)卷組存在性判斷
  • 核心條件:"'research' in ansible_facts.lvm.vgs"
    • ansible_facts.lvm.vgs是Ansible收集的facts信息,包含所有卷組名稱
    • research在卷組列表中時,執行block部分;否則執行"卷組不存在"的錯誤提示
(3)模塊說明
  • lvol:用于管理邏輯卷(創建、修改、刪除),需指定vg(卷組)、lv(邏輯卷名)、size(大小)
  • filesystem:用于格式化存儲設備,需指定fstype(文件系統類型)和dev(設備路徑)
  • debug:用于輸出自定義消息(錯誤提示)
3. 執行結果分析
  • node1

    • research卷組大小為2G,足夠創建1500MiB邏輯卷
    • block中的"創建1500MiB"任務成功,rescue不觸發
    • always執行,格式化邏輯卷
    • 最終結果:1500MiB的/dev/research/data被創建并格式化為ext4
  • node2

    • research卷組大小為1G(1024MiB),無法創建1500MiB邏輯卷
    • block中的任務失敗,觸發rescue
    • 輸出錯誤消息Could not create logical volume of that size,并創建800MiB邏輯卷
    • always執行,格式化邏輯卷
    • 最終結果:800MiB的/dev/research/data被創建并格式化為ext4
  • 在無research卷組的節點上

    • 跳過block部分,執行"卷組不存在"的錯誤提示
    • 最終結果:輸出Volume group does not exist

二、擴展例題:錯誤處理高級用法

(一)fail模塊:條件滿足時中斷Playbook

1. 功能說明

fail模塊用于在滿足特定條件時主動中斷Playbook執行,并輸出自定義錯誤消息,常與when配合使用。

2. 完整代碼(c.yml
---
- name: test fail module (測試fail模塊中斷功能)hosts: node1tasks:# 任務1:執行shell命令,輸出含"error"的字符串- name: shellshell:cmd: echo 'this is a string for testing--error'  # 輸出包含"error"的內容register: return_value  # 注冊命令結果到變量return_value# 任務2:當命令輸出含"error"時,中斷Playbook- name: failfail:msg: Conditions established, Interrupt running playbook  # 中斷提示消息when: "'error' in return_value.stdout"  # 條件:命令輸出中包含"error"# 任務3:因Playbook被中斷,此任務不會執行- name: debugdebug:msg: I never execute, because the playbook has stopped
3. 執行結果
  • 任務1執行成功,輸出含"error"的字符串
  • 任務2的條件滿足('error' in return_value.stdouttrue),執行fail模塊,Playbook中斷
  • 任務3不會執行

(二)failed_when:自定義任務失敗條件

1. 功能說明

failed_when用于自定義任務的"失敗條件",即使任務實際執行成功(返回碼0),若滿足failed_when條件,也會被標記為失敗。

2. 完整代碼
---
- name: test failed_when (測試自定義失敗條件)hosts: node1tasks:# 任務1:正常執行的debug- name: debugdebug:msg: I execute normally  # 正常輸出# 任務2:當命令輸出含"error"時,標記為失敗- name: shellshell:cmd: echo 'this is a string testing--error'  # 輸出包含"error"的內容register: return_value  # 注冊結果failed_when: "'error' in return_value.stdout"  # 自定義失敗條件# 任務3:因任務2被標記為失敗,默認情況下此任務不會執行- name: debug2debug:msg: chenyu
3. 執行結果
  • 任務1正常執行,輸出消息
  • 任務2的shell命令實際執行成功(返回碼0),但因'error' in return_value.stdouttrue,被failed_when標記為失敗
  • 任務3默認不會執行(Playbook在任務失敗后中斷)

(三)ignore_errors: yes:忽略錯誤繼續執行

1. 功能說明

ignore_errors: yes用于忽略當前任務的錯誤,即使任務失敗,Playbook也會繼續執行后續任務。

2. 完整代碼
---
- name: test ignore_errors (測試忽略錯誤)hosts: node1tasks:# 任務1:輸出主機名(正常執行)- name: debug1debug:msg: "{{ ansible_fqdn }}"  # 輸出節點的完全限定域名# 任務2:引用不存在的變量(會失敗,但被忽略)- name: debug2debug:msg: "{{ ansible_ip }}"  # ansible_ip是不存在的變量,會報錯ignore_errors: yes  # 忽略當前任務的錯誤# 任務3:創建文件(因任務2的錯誤被忽略,此任務會執行)- name: create filefile:path: /tmp/abc  # 文件路徑state: touch    # 確保文件存在(不存在則創建)
3. 執行結果
  • 任務1正常執行,輸出主機名
  • 任務2因引用不存在的變量ansible_ip而失敗,但ignore_errors: yes使其被忽略
  • 任務3繼續執行,在/tmp下創建abc文件

(四)changed_when:自定義任務狀態

1. 功能說明

changed_when用于自定義任務的"變更狀態"(changed/ok),即使任務實際修改了系統狀態,也可通過此參數強制標記為ok,反之亦然。

2. 完整代碼(強制標記為changed
---
- name: test changed_when (測試自定義變更狀態)hosts: node1tasks:# 任務1:debug模塊默認不會標記為changed,通過changed_when強制標記- name: debug1debug:msg: "{{ ansible_fqdn }}"changed_when: true  # 強制標記為"changed"(即使實際未變更系統)
3. 完整代碼(強制標記為ok
---
- name: test changed_when (測試自定義變更狀態)hosts: node1tasks:# 任務1:ls命令默認不會標記為changed,此處顯式指定- name: shellshell:cmd: ls /tmp  # 僅查詢,不修改系統狀態changed_when: false  # 強制標記為"ok"(即使實際可能有隱含變更)
4. 執行結果
  • changed_when: true:任務執行后狀態為changed(綠色輸出)
  • changed_when: false:任務執行后狀態為ok(黃色輸出)

三、總結:錯誤處理核心方法對比

方法作用適用場景示例代碼片段
block/rescue/always批量任務錯誤捕獲與處理復雜流程(嘗試→失敗處理→最終操作)block: ... rescue: ... always: ...
fail模塊條件滿足時主動中斷Playbook關鍵條件不滿足時需終止執行fail: msg="中斷" when: 條件
failed_when自定義任務失敗條件需基于命令輸出判斷任務是否失敗failed_when: "'error' in return.stdout"
ignore_errors: yes忽略任務錯誤,繼續執行后續任務非關鍵任務失敗不影響整體流程ignore_errors: yes
changed_when自定義任務變更狀態(changed/ok需精確控制任務狀態顯示(如審計、報告)changed_when: truechanged_when: false

通過上述方法,可實現Ansible Playbook的精細化錯誤控制,確保在復雜場景下的穩定性與可維護性。

for循環和if的例題

1,從 http://ansible.example.com/materials/newhosts.j2 下載模板文件

完成該模板文件,用來生成新主機清單(主機的顯示順序沒有要求),結構如下:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.122.10 node1.example.com node1
192.168.122.20 node2.example.com node2
192.168.122.30 node3.example.com node3
192.168.122.40 node4.example.com node4
192.168.122.50 node5.example.com node5
創建劇本/home/student/ansible/newhosts.yml,它將使用上述模板在 test01 主機組的主機上
生成文件/etc/newhosts。

使用 group.all 變量生成主機清單的實現

如果需要使用 group.all 變量(包含所有主機)來生成主機清單,我們可以通過 Ansible 的內置變量和 Jinja2 模板來實現。這種方法更靈活,能自動包含清單中的所有主機。

一、修改后的模板文件 newhosts.j2

下載模板文件 curl -0 http://ansible.example.com/materials/newhosts.j2

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for ycy in groups.all %}
{{ hostvars[ycy].ansible_default_ipv4.address }}        {{ hostvars[ycy].ansible_fqdn }}        {{ hostvars[ycy].ansible_hostname }}
{% endfor %}

模板說明

  1. 保留本地主機條目

    • 前兩行保持不變,包含 IPv4 和 IPv6 的本地主機配置
  2. 使用 group.all 遍歷所有主機

    • groups.all 是 Ansible 的內置變量,包含清單中所有主機
    • for host in groups.all 循環遍歷所有主機

二、適配的生成主機清單劇本 newhosts.yml

?

---
- name: get facthosts: all
- name: template inventoryhosts: test01tasks:- name: test1template:src: /home/student/ansible/newhosts.j2dest: /etc/newhosts

三、執行與驗證

  1. 執行劇本:
ansible-playbook /home/student/ansible/newhosts.yml
  1. 驗證結果:
    登錄test01主機組中的主機,檢查生成的/etc/newhosts文件:
cat /etc/newhosts

應該能看到包含本地主機和所有節點(node1到node5)的完整主機清單,格式與要求一致。

2,編寫劇本修改遠程文件內容

創建劇本 /home/student/ansible/newissue.yml,滿足下列要求:
1)在所有清單主機上運行,替換/etc/issue 的內容
2)對于 test01 主機組中的主機,/etc/issue 文件內容為 test01
3)對于 test02 主機組中的主機,/etc/issue 文件內容為 test02
4)對于 web 主機組中的主機,/etc/issue 文件內容為 Webserver

(一)題目需求

  1. 創建劇本/home/student/ansible/newissue.yml,在所有清單主機上運行。
  2. 按主機組設置/etc/issue內容:
    • test01主機組:內容為test01
    • test02主機組:內容為test02
    • web主機組:內容為Webserver

(二)核心技術點

  • group_names變量:Ansible內置變量,存儲當前主機所屬的所有主機組,用于條件判斷。
  • Jinja2if-elif邏輯:在copy模塊的content參數中嵌入條件,實現基于主機組的差異化內容配置。
  • copy模塊:直接通過content參數設置文件內容,無需本地文件,簡化配置流程。

(三)完整實現步驟

1. 編寫newissue.yml劇本

劇本通過group_names判斷主機所屬組,結合if-elif邏輯動態設置/etc/issue內容,確保所有主機按組匹配正確配置。

# /home/student/ansible/newissue.yml
---
- name: Configure /etc/issue based on host grouphosts: all  # 在所有清單主機上執行tasks:- name: Set /etc/issue content by host groupcopy:content: |{% if 'test01' in group_names %}test01{% elif 'test02' in group_names %}test02{% elif 'web' in group_names %}Webserver{% endif %}dest: /etc/issue  # 目標文件路徑
  • 劇本邏輯說明
    • hosts: all:覆蓋所有清單主機,無需分組執行,簡化操作。
    • group_names:無需收集facts即可使用,存儲當前主機的組列表(如test01主機的group_names['test01'])。
    • if-elif條件:
      1. 優先判斷是否屬于test01組,是則內容為test01
      2. 否則判斷是否屬于test02組,是則內容為test02
      3. 否則判斷是否屬于web組,是則內容為Webserver
      4. 若主機不屬于上述任何組,/etc/issue將為空(無else分支,不設置默認內容)。
    • copy模塊的content參數:直接嵌入多行文本與Jinja2邏輯,無需額外創建本地文件,高效便捷。

(四)執行與驗證

1. 執行劇本
ansible-playbook /home/student/ansible/newissue.yml
2. 分主機組驗證
  • test01主機組

    [student@master ansible]$ ansible node1 -m shell -a "cat /etc/issue"
    node1 | CHANGED | rc=0 >>
    test01
    
  • test02主機組

    [student@master ansible]$ ansible test02 -m shell -a "cat /etc/issue"
    node2 | CHANGED | rc=0 >>
    test02
    
  • web主機組

    [student@master ansible]$ ansible web -m shell -a "cat /etc/issue"
    node4 | CHANGED | rc=0 >>
    webserver
    node3 | CHANGED | rc=0 >>
    webserver
    

三、關鍵技術總結

技術點作用適用場景示例代碼片段
groups.all遍歷清單中所有主機批量生成包含所有主機的配置(如主機清單){% for host in groups.all %}...{% endfor %}
hostvars獲取指定主機的facts信息(IP、主機名)動態獲取主機屬性用于配置生成hostvars[host]['ansible_fqdn']
group_names查看當前主機所屬的所有組基于主機組的差異化配置(如文件內容){% if 'test01' in group_names %}
Jinja2for循環批量生成重復結構的配置主機清單、批量用戶創建等{% for host in groups.all %}...{% endfor %}
Jinja2if-elif邏輯基于條件動態設置內容按組/按主機屬性差異化配置{% if 'test01' in group_names %}test01{% endif %}
template模塊渲染包含變量/邏輯的模板文件復雜配置文件生成(如主機清單、Nginx配置)src: newhosts.j2 dest: /etc/newhosts
copy模塊content直接設置文件內容,無需本地文件簡單文本文件配置(如/etc/issue、標語文件)content: "test01" dest: /etc/issue

四、注意事項

  1. groups.all使用限制:若清單中包含非node1-node5的主機,需在模板中添加條件過濾(如{% if 'node' in host %}...{% endif %}),避免生成多余條目。
  2. gather_facts開關:題目一中必須開啟gather_facts: yes,否則hostvars無法獲取主機名;題目二無需開啟,減少執行時間。
  3. 權限與歸屬/etc/newhosts/etc/issue均為系統配置文件,需設置root所有權與0644權限,避免權限不足導致解析失敗。
  4. 多組歸屬優先級:若主機同時屬于多個組(如某主機既在test01也在web),if-elif會優先匹配第一個條件(即test01),需確保主機組劃分唯一。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/95512.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/95512.shtml
英文地址,請注明出處:http://en.pswp.cn/web/95512.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在linux下使用MySQL常用的命令集合

1. 數據庫查看和選擇-- 查看所有數據庫 SHOW DATABASES;-- 選擇使用某個數據庫&#xff08;需要修改&#xff1a;your_database_name&#xff09; USE your_database_name;-- 查看當前正在使用的數據庫 SELECT DATABASE();說明&#xff1a;your_database_name 替換為你要操作的…

mysy2使用

參考鏈接 https://blog.csdn.net/qq_36525177/article/details/115279468 介紹 要把linux程序在windows上編譯&#xff0c;且最好兼容posix標準&#xff0c;就用msys2。 使用 1、先下載安裝&#xff0c;我裝在D:\mysy2 2、打開vscode&#xff0c;不要切換目錄&#xff0c;…

【Protues仿真】基于AT89C52單片機的溫濕度測量

目錄 0案例視頻效果展示 1DHT11溫度濕度傳感器 1.1傳感器簡介 1.2引腳定義&#xff08;從左到右&#xff0c;面對網格面&#xff09; 1.3時序 & 校驗&#xff08;原理速覽&#xff09; 1.4常見故障排查 2 DHT11溫度濕度傳感器數據 2.1 DHT11溫度濕度傳感器數據格式…

JavaScript箭頭函數與普通函數:兩種工作方式的深度解析

文章目錄JavaScript箭頭函數與普通函數&#xff1a;兩種"工作方式"的深度解析 &#x1f3f9;&#x1f19a;&#x1f468;&#x1f4bc;引言&#xff1a;為什么需要箭頭函數&#xff1f;核心區別全景圖對比表格&#xff1a;箭頭函數 vs 普通函數關系示意圖一、this綁定…

藍光三維掃描技術賦能內衣胸墊設計:從精準制造到個性化體驗的革新之旅

在競爭激烈的內衣市場中&#xff0c;產品設計的精準性、舒適度和個性化已成為品牌制勝的關鍵。傳統內衣設計依賴主觀經驗與樣品反復調整&#xff0c;不僅周期長、成本高&#xff0c;且難以實現對復雜胸型的精準適配。為應對這一挑戰&#xff0c;某知名內衣品牌采用新拓三維XTOM…

內存保護單元MPU

一、介紹內存保護單元 是一種硬件模塊&#xff0c;通常集成在處理器內核中&#xff0c;用于管理和管理對內存的訪問&#xff0c;以提高系統的可靠性和安全性。它的核心任務是保護。想象一下&#xff0c;一個操作系統中有多個任務在運行&#xff1a;* 任務A的代碼 bug 可能會錯誤…

【Kubernetes知識點】監控升級,備份及Kustomize管理

目錄 1.舉例說明K8s中都有哪些常規的維護管理操作。 2.如何升級K8s到新的版本&#xff1f;在升級過程中應該注意哪些事項&#xff1f; 3.解釋ETCD及其備份和恢復的過程。 4.Kustomization在Kubernetes中的作用 1.舉例說明K8s中都有哪些常規的維護管理操作。 集群狀態監控…

《Effective Java》第4條:通過私有構造器強化不可實例化的能力

說明&#xff1a; 關于本博客使用的書籍&#xff0c;源代碼Gitee倉庫 和 其他的相關問題&#xff0c;請查看本專欄置頂文章&#xff1a;《Effective Java》第0條&#xff1a;寫在前面&#xff0c;用一年時間來深度解讀《Effective Java》這本書 正文&#xff1a; 原文P15&am…

20.Linux進程信號(一)

信號: 產生->保存->處理一、預備知識信號vs信號量->沒有任何關系什么叫做信號&#xff1f;中斷我們正在做的事情&#xff0c;是一種事件的異步通知機制。同步和異步理解&#xff1a;同步指事件發生具有一定的順序性&#xff08;如命名管道中服務端讀方式打開會阻塞&am…

【C++】Vector核心實現:類設計到迭代器陷阱

vector 模擬實現代碼的核心下面從類設計、核心接口、內存安全、常見陷阱、測試場景5 個維度&#xff0c;提煉需重點掌握的知識點&#xff0c;覆蓋面試高頻考點與實踐易錯點&#xff1a;一、類結構與成員變量&#xff08;基礎框架&#xff09;vector 的核心是通過三個迭代器&…

并發編程指南 內存模型

文章目錄5.1 內存模型5.1.1 對象和內存位置5.1.2 對象、內存位置和并發5.1.3 修改順序5.1 內存模型 內存模型&#xff1a;一方面是內存布局&#xff0c;另一方面是并發。并發的基本結構很重要&#xff0c;特別是低層原子操作。因為C所有的對象都和內存位置有關&#xff0c;所以…

血緣元數據采集開放標準:OpenLineage Integrations Compatibility Tests Structure

OpenLineage 是一個用于元數據和血緣采集的開放標準&#xff0c;專為在作業運行時動態采集數據而設計。它通過統一的命名策略定義了由作業&#xff08;Job&#xff09;、運行實例&#xff08;Run&#xff09;和數據集&#xff08;Dataset&#xff09; 組成的通用模型&#xff0…

執行一條select語句期間發生了什么?

首先是連接器的工作&#xff0c;嗯&#xff0c;與客戶端進行TCP三次握手建立連接&#xff0c;校驗客戶端的用戶名和密碼&#xff0c;如果用戶名和密碼都對了&#xff0c;那么就會檢查該用戶的權限&#xff0c;之后執行的所有SQL語句都是基于該權限接著客戶端就可以向數據庫發送…

element el-select 默認選中數組的第一個對象

背景&#xff1a;在使用element組件的時候&#xff0c;我們期望默認選中第一個數值。這里我們默認下拉列表綁定的lable是中文文字&#xff0c;value綁定的是數值。效果展示&#xff1a;核心代碼&#xff1a;<template><el-select v-model"selectValue" plac…

【論文閱讀】LightThinker: Thinking Step-by-Step Compression (EMNLP 2025)

論文題目&#xff1a;LightThinker: Thinking Step-by-Step Compression 論文來源&#xff1a;EMNLP 2025&#xff0c;CCF B 論文作者&#xff1a; 論文鏈接&#xff1a;https://arxiv.org/abs/2502.15589 論文源碼&#xff1a;https://github.com/zjunlp/LightThinker 一、…

ABAQUS多尺度纖維增強混凝土二維建模

本案例是通過ABAQUS對論文Study on the tensile and compressive mechanical properties of multi-scale fiber-reinforced concrete: Laboratory test and mesoscopic numerical simulation&#xff08;https://doi.org/10.1016/j.jobe.2024.108852&#xff09;中纖維增強混凝…

C++ ---- 模板的半特化與函數模板的偏特化

在 C 中&#xff0c;模板提供了一種強大的泛型編程方式&#xff0c;使得我們能夠編寫類型無關的代碼。然而&#xff0c;在實際使用中&#xff0c;有時我們需要根據具體的類型或類型組合對模板進行定制&#xff0c;這時就需要用到模板的特化。本文將介紹半模板特化和函數模板的偏…

為何 React JSX 循環需要使用 key

key 是 React 用于識別列表中哪些子元素被改變、添加或刪除的唯一標識符 它幫助 React 更高效、更準確地更新和重新渲染列表 1、核心原因&#xff1a;Diff算法與性能優化 React 的核心思想之一是通過虛擬 DOM (Virtual DOM) 來減少對真實 DOM 的直接操作&#xff0c;從而提升性…

Jetson AGX Orin平臺R36.3.0版本1080P25fps MIPI相機圖像采集行缺失調試記錄

1.前言 主板:AGX Orin 官方開發套件 開發版本: R36.3.0版本 相機參數如下: 相機硬件接口: 2. 梳理大致開發流程 核對線序/定制相機轉接板 編寫camera driver驅動 編寫camera dts配置文件 調camera參數/測試出圖 前期基本流程就不多介紹了直接講正題 3. 問題描述 …

力扣hot100:螺旋矩陣(邊界壓縮,方向模擬)(54)

在解決螺旋矩陣問題時&#xff0c;我們需要按照順時針螺旋順序遍歷矩陣&#xff0c;并返回所有元素。本文將分享兩種高效的解決方案&#xff1a;邊界收縮法和方向模擬法。題目描述邊界收縮法邊界收縮法通過定義四個邊界&#xff08;上、下、左、右&#xff09;來模擬螺旋遍歷的…