RHCE(ansible語句)

q_7發表於2024-04-03

一:when語句

1:基礎瞭解

說到底,還是有多個表示式來組成一個判斷語句,很多種的判斷語句

1、 為什麼需要判斷語句:

有的時候play的結果需要依賴於變數,fact或者是前一個任務的執行結果,或者基於上一個task執行返回的結果而決定如何執行後續的task,這個時候就需要條件的判斷了,一個很簡單的案例,就是掛載磁碟,不需要到被控節點上面去看是否掛成功了,直接使用一個判斷,看那個task任務的執行的結果,為0則代表著成功,就進行下一步的任務的執行

2、使用場景

  1)目標主機上定義了一個硬限制,比如目標主機的最小記憶體必須達到多少,才能執行task任務

  2)捕獲一個命令的輸出,根據輸出的結果不同來觸發不同的task

  3)根據不同的目標主機的facts,來執行不同的tasks,如果是node1就是執行A任務,如果是node2就執行B任務

  等等等

3、when理解

當判斷的結果是一致的話,那麼執行task任務,否則的話,就跳過這個任務

ansible中判斷語句是when判斷,預設when判斷,就識別變數,所以的話,不需要使用"{{}}"來引用變數,when inventory_hostname == 'node1'

還有一個點就是如果不使用變數的話,就只使用這個值的話,那麼的話就要帶上這個雙引號,並且裡面還要有單引號即可

when與模組的層級是一樣的

2:判斷的表示式

1:比較運算子

== 比較2邊是否相等的,比較字串和數字

!=  2邊是否一致,不一致則為真

>=  比較大小,左邊大於右邊為真

<=  右邊大於左邊為真

>  左邊大於右邊為真

<  右邊大於左邊為真

案例:

判斷執行的task任務的主機是不是node1,如果是的node1則執行任務,

判斷主機的freemem大小是否大於1000,如果是的話,則執行任務

//透過facts變數來獲取這個記憶體,然後透過魔法變數來獲取這個node1
- name: memfree
  hosts: node1
  tasks:
    - name: use when
      debug:
        msg: dayu1000
      when: ansible_memtotal_mb > 1000
    - name: node1
      debug:
        msg: hostname is node1
      when: inventory_hostname == 'node1'

2:邏輯運算子

and 邏輯與,2邊都為真,則返回真
or 邏輯或,有一個為真,則返回為真
not 邏輯否,對錶達式取反,真為假,假為真,在表示式的前面寫上
() 當一組的表示式組合在一起後,形成一個更大的表示式,組合內的所有表示式都是邏輯與的關係

案例:

#判斷主機名為node1,ip地址為10,則列印hello rhce
[root@controller mnt]# cat f4.yml 
- name: use debug
  hosts: node1
  tasks:
    - debug:
        msg: hello rhce
      when: inventory_hostname == 'node1' and ansible_ens160.ipv4.address == '172.25.250.11'

#判斷主機名是否為node1或者ip地址是30的,則列印rhce
[root@controller mnt]# cat f5.yaml 
- name:
  hosts: all
  tasks:
    - debug:
       msg: rhce
      when: inventory_hostname == 'node1' or ansible_ens160.ipv4.address == '172.25.250.30'

#使用not來進行判斷,判斷不是node1的主機即執行任務
應該放在最前面
- name: user kkk
  hosts: all
  tasks:
    - name:
      debug:
        msg: hello
      when: not ansible_hostname == 'node1'


#()的使用,主機名是node1並且ip地址是11或者系統是redhat,並且版本是9的則執行任務
()裡面是邏輯與的關係,多個表示式一起表達
[root@controller mnt]# cat f7.yml 
- name: use debug
  hosts: all
  tasks:
    - debug:
        msg: hello rhce
      when: (ansible_hostname == 'node1' and ansible_ens160.ipv4.address == '172.25.250.11') or (ansible_distribution_major_version == '9' and ansible_os_family == 'RedHat')

3:根據rc的返回值來進行判斷task任務是否執行成功

根據註冊變數,這個能儲存上一個tasks任務的執行資訊,就是根據rc的值為0則表示執行成功,執行任務,不成功,執行另外的一個任務

[root@controller mnt]# cat f8.yml 
- hosts: node1
  tasks:
    - shell: ls /etc/passsssss
      register: get_status
      ignore_errors: yes
    - debug:
       msg: rc is 0
      when: get_status.rc == 0
    - debug:
       msg: rc is error
      when: get_status.rc != 0

4:透過條件判斷路徑是否存在

shell指令碼也有這個使用test -f 路徑,判斷是否是一個檔案,-d判斷是否是一個目錄,-e 路徑,判斷路徑是否存在

ansible中,判斷的格式如下

file:判斷指定路徑是否為一個檔案,是則為真

directory:判斷指定路徑是否是一個目錄,是則為真

link:判斷指定路徑是否為一個軟連線,是則為真

mount:判斷路徑是否為掛載點,是則為真

exists:判斷指定路徑是否存在,存在則為真

使用when來進行判斷 when "'/etc/passwd' is exists "

使用的關鍵字就是is

使用變數的值進行判斷

#/etc/passwd存在的話,就執行任務
#when直接使用值的話需要使用雙引號裡面的值在加上單引號即可
[root@controller mnt]# cat f9.yaml 
- hosts: all
  tasks:
    - debug:
       msg: exist
      when: "'/etc/passwd is exists'"

5:透過判斷tasks任務的執行結果(是對整個task任務進行判斷)

ok:目標狀態和期望值一致,沒有發生變更

change或changed:目標發生變更,與期望值一樣

sucess或succeeded:目標狀態與期望值一樣,或者任務執行成功了

failure或failed:任務失敗

skip或skipped:任務跳過,注意,如果一個錯誤的任務使用ignore_errors忽略了這個錯誤,會跳過,但是實際上這個任務的執行是失敗的,並沒有跳過注意) 

案例:

#使用一個錯誤的任務,錯誤的結果就執行任務
- hosts: all
  tasks:
    - shell: ls /etc/passssss
      register: get_status
      ignore_errors: yes
    - debug:
       msg: is filed
      when: get_status is failed
    - debug:
       msg: is skipped
      when: get_status is skip  

6:透過對變數進行判斷

defined:判斷變數是否已定義了,定義了則返回真

undefined:判斷變數是否未定義,未定義則返回真

none:判斷變數的值是否為空,如果變數的已定義但是值為空的話,則返回真,定義了這個變數名,但是沒有值

案例:

#定義一個變數,然後不給他的值,則執行任務
- hosts: node1
  vars:
    rhel:
  tasks:
    - debug:
       msg: is none
      when: rhel is none
    - debug:
       msg: is undefined
      when: rhel is undefined  

7:透過字串進行判斷大小寫字母

lower:判斷字串是否是小寫字母

upper:判斷字串是否是大寫字母

[root@controller mnt]# cat f12.yml 
- hosts: node1
  vars:
    rhel: qqqq
  tasks:
    - debug:
       msg: lower
      when: rhel is lower  

8:透過數字來進行判斷

even:判斷數值是否為偶數,是則為真

odd:判斷數值是否為奇數,,是則為真

divisibleby(num):判斷是否可以整除指定的數值,是則為真

#判斷能被2整除嗎。是的話就執行任務
[root@controller mnt]# cat f12.yml 
- hosts: node1
  vars:
    rhel: 10
  tasks:
    - debug:
       msg: oushu
      when: rhel is divisibleby(2)

9:透過判斷是否是子集或者是父集,in的判斷

數字和字元都行

subset():判斷一個list是不是另外一個list的子集,when: a is subnet(b)

就是判斷a是不是b的子集,就是a是不是被包含在b裡面,小的

superset():判斷一個list是不是另外一個list的父集;when: b is superset(a)

判斷a是不是b的父集,就是a是不是包含b,大的

寫法的話就是使用列表的形式來編寫,不能使用字典的形式,會出現錯誤

案例:

[root@controller mnt]# cat f13.yml 
- hosts: node1
  vars:
    f:
      - qqq
      - www
    w:
      - qqq
  tasks:
    - debug:
       msg: fuji
      when: f is superset(w)   

判斷字串是否位於一個列表中的(非常重要的,經常使用的)

判斷ens160網路卡是不是在ansible_intreafces裡面

[root@controller mnt]# cat f3.yml 
- hosts: node1
  tasks:
    - debug:
       msg: ens160 exists
      when: "'ens160' in ansible_interfaces"

10:判斷物件是否是字串或者數字

string:判斷是否是字串

numbber:判斷是否是數字

[root@controller mnt]# cat f14.yml 
- hosts: node1
  vars:
    rhel: 9
  tasks:
    - debug:
       msg: 9 is number
      when: rhel is number

3:when判斷和其他的關鍵字

1、block關鍵字

使用when判斷的時候,每一個when判斷只會判斷一個task任務,如果有多個的話,就需要編寫多次的,這樣的話,程式碼就非常的多且不必要了

解決的方法就是: 

ansible透過block包裹多個tasks的任務,直接對block進行when判斷,如果判斷成功,則執行block中的所有tasks任務

通俗來講就是block是一個塊,把多個tasks任務作為一個整體,對block進行判斷,如果成立則block中的tasks任務執行

案例:
建立一個檔案,建立一個目錄,然後對其進行判斷,直接對這個block進行判斷,判斷主機名是node1執行

#上面所述就有2個tasks任務,如果使用when的話,要使用2次,使用block的話,直接對這個block這個整體進行判斷,即能執行
block的層級是包裹這些任務的,然後when對這個block進行判斷,成功,則執行這個任務
- name: use block
  hosts: all
  tasks:
    - block:
      - file: 
          path: /mnt/1.txt
          state: touch
      - file:
          path: /mnt/1.dir
          state: directory
      when: inventory_hostname == 'node1'

2、resuce關鍵字

層級與block一樣的,錯誤拯救,對於block塊的話,如果block中的任務執行失敗,則會執行resuce下面的任務,如果沒有失敗的話,則不會觸發resuce關鍵字下的task任務

- name: rescue
  hosts: all
  tasks:
    - block:
       - shell: ls /etc/p11111
       - file:
          path: /etc/passwd
          state: file
      rescue:
        - debug:
           msg: rescue
      when: inventory_hostname == 'node1'

3、always關鍵字

無論block任務執行成功還是失敗,都要執行always關鍵字的中task任務

- name: rescue
  hosts: all
  tasks:
    - block:
       - shell: ls /etc/p11111
       - file:
          path: /etc/passwd
          state: file
      rescue:
        - debug:
           msg: rescue
      always:
         - debug:
            msg: always
      when: inventory_hostname == 'node1'

4、fail和failed_when  

如果一個task任務執行失敗的話,後面的task任務也沒有必要執行,需要執行退出

就是掛載都沒有掛上去,就不需要寫yum倉庫等等

案例:

- name: faile
  hosts: node1
  tasks:
    - shell: ls /etc/lllll
      ignore_errors: yes
      register: get_status
    - fail:
          msg: juben exit
      when: get_status.rc != 0
    - debug:
       msg: a

思路:
忽略了錯誤,繼續像下面執行任務,本來要列印這個a的,使用了fail關鍵字,符合條件就退出這個劇本

failed_when:關鍵字

案例:

- name: faile
  hosts: node1
  tasks:
    - shell: ls /etc/lllll
      ignore_errors: yes
      register: get_status
    - debug:
        msg: juben exit
      failed_when: get_status.rc != 0
    - debug:
       msg: a

二:ansible迴圈語句

迴圈語句進行批次化的操作,建立使用者,建立檔案等

1:基於列表的迴圈(with_items)

不能使用物件(字典)的方式進行迴圈,會報錯的,item固定的格式

2種寫法
第一種,利用變數的形式
- name: item
  hosts: node1
  vars:
    users:
      - zhangsan
      - lisi
      - wangwu
  tasks:
    - debug:
       msg: "{{item}}"
      with_items: "{{users}}"

#with_items遍歷users裡面的元素

第二種寫法:
直接在with_items後面寫
- name: item
  hosts: node1
  tasks:
    - debug:
       msg: "{{item}}"
      with_items: 
         - zhangsan
         - lisi
         - wangwu
但是這種方式不常用

2:基於字典的迴圈(with_dict)

就是鍵值對的方式來進行迴圈

- name: dict
  hosts: node1
  vars:
    users:
      q1:
       uid: 2022
       name: zhangsan
      q2:
       uid: 2023
       name: lisi
  tasks:
    - debug:
       msg: "{{item.value.name}}"
      with_dict: "{{users}}"

###輸出的結果
ok: [node1] => (item={'key': 'q1', 'value': {'uid': 2022, 'name': 'zhangsan'}}) => {
    "msg": "zhangsan"
}
ok: [node1] => (item={'key': 'q2', 'value': {'uid': 2023, 'name': 'lisi'}}) => {
    "msg": "lisi"
}


//思路
key是q1,value是uid,name,然後想要輸出什麼就以.連線

3:loop迴圈

天生是用來遍歷列表的,但是也可以遍歷字典,需要過濾器等

- name: loop
  hosts: node1
  vars:
    users:
      - zhangsan
      - lisi
      - wangwu
  tasks:
    - debug:
       msg: "{{item}}"
      loop: "{{users}}"

過濾器等

dict2items將字典轉換成列表

使用者的密碼password_hash等

三:總結

when判斷有很多的方式來進行判斷,facts變數,註冊變數,in判斷等等

還有幾個關鍵字,block,rescue,always,fail,failed_when

迴圈語句,最常用的就是loop迴圈

相關文章