Linux的控制语句

Linux的控制语句

本章主要介绍 playbook中的控制语句。
使用 when 判断语句

block-rescue判断

循环语句

一个play中可以包含多个task,如果不想所有的task全部执行,可以设置只有满足某个条件才执行这个task,不满足条件则不执行此task。本章主要讲解when 和 block-rescue两种判断语句。

1 判断语句when

when作为一个判断语句,出现在某个 task下,格式如下。

tasks:
 ‐ name: aa
 模块1
 when: 条件1

如果条件1成立,则执行模块1,否则不执行。

注意:在when中引用变量时是不用加{{}}的。

本章实验都在/home/duan/demo3下操作,先把 demo3目录创建出来并把ansible.cfg和 hosts拷贝进去,命令如下。

Session lifetime based on X11 requested, but X11 initialization failed.
[blab@rh1 ~]$ mkdir demo3
[blab@rh1 ~]$ cp ansible.cfg hosts demo3/
[blab@rh1 ~]$ cd demo3
[blab@rh1 demo3]$ 

1.1when判断中>、<、!=的使用

写一个playbook,判断某条件是否成立,成立了才执行task,否则不执行,命令如下。

[blab@rh1 demo3]$ cat when-1.yaml 
---
- hosts: rh2
  tasks:
  - name: task1
    debug: msg="111"
    when: 1<2

这里有一个task,判断1<2是否成立,如果成立则执行task1,屏幕上会显示111;如果不成立则不执行taskl,屏幕上不会显示111。这里明显是成立的,所以会执行task1。运行结果如下。

[blab@rh1 demo3]$ ansible-playbook when-1.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [task1] ******************************************************************************************
ok: [rh2] => {
    "msg": "111"
}

PLAY RECAP ********************************************************************************************
rh2                        : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

when后面可以有多个条件,用or或and作为连接符。

如果用or作为连接符,只要有一个条件成立即可,只有所有的条件都不成立时,整体才不成立。

修改when-1.yaml的内容如下。


[blab@rh1 demo3]$ cat when-1.yaml 
---
- hosts: rh2
  tasks:
  - name: task1
    debug: msg="111"
    when: 1 < 2 or 2 > 3

此处用or作为连接符,只要有一个条件成立就会成立,2>3不成立,但是1<2成立,所以整体上就是成立的。运行结果如下。

[blab@rh1 demo3]$ ansible-playbook when-1.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [task1] ******************************************************************************************
ok: [rh2] => {
    "msg": "111"
}

PLAY RECAP ********************************************************************************************
rh2                        : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

仍然会执行task1。

修改when-1.yaml的内容如下。

[blab@rh1 demo3]$ cat when-1.yaml 
---
- hosts: rh2
  tasks:
  - name: task1
    debug: msg="111"
    when: 1 > 2 or 2 > 3

此处用or作为连接符,1>2不成立且2>3也不成立,所以整体上就是不成立的,不会执行task1。运行结果如下。

[blab@rh1 demo3]$ ansible-playbook when-1.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [task1] ******************************************************************************************
skipping: [rh2]

PLAY RECAP ********************************************************************************************
rh2                        : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

也可以用and作为连接符,如果用and作为连接符,需要所有条件全部成立,只要有一个条件不成立,整体上就是不成立的。

修改when-1.yaml的内容如下。

[blab@rh1 demo3]$ cat when-1.yaml 
---
- hosts: rh2
  tasks:
  - name: task1
    debug: msg="111"
    when: 1 < 2 and 2 > 3

这里虽然1<2是成立的,但是2>3不成立,所以整体上就是不成立的,因为用and作为连接符,需要所有的条件都成立才可以,所以不会执行task1。运行结果如下。

[blab@rh1 demo3]$ ansible-playbook when-1.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [task1] ******************************************************************************************
skipping: [rh2]

PLAY RECAP ********************************************************************************************
rh2                        : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

在判断中,or 和 and是可以混用的,为了看得更清晰,可以使用小括号。

修改 when-1.yaml 的内容如下。

[blab@rh1 demo3]$ cat when-1.yaml 
---
- hosts: rh2
  tasks:
  - name: task1
    debug: msg="111"
    when: ( 1>2 or 2!=1 ) and 2 > 3

这里(1>2 or 2!=1)作为一个整体,1>2不成立,但是2!=1(=是不等于的意思)成立,所以此处( 1>2 or 2!=1)作为一个整体是成立的。and后面2>3不成立,所以整个when后面的判断是不成立的,不会执行此 task1。运行结果如下。

[blab@rh1 demo3]$ ansible-playbook when-1.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [task1] ******************************************************************************************
skipping: [rh2]

PLAY RECAP ********************************************************************************************
rh2                        : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

常见的判断符包括以下6种。
(1)==:等于。
(2)!=:不等于。
(3)>:大于。
(4)>=:大于等于。
(5)<:小于。
(6)<=:小于等于。

如果rh2的系统主版本是7(RHEL/CentOS7),则打印111,否则不打印。
playbook的内容如下。

[blab@rh1 demo3]$ cat when-2.yaml 
---
- hosts: rh2
  tasks:
  - name: task1
    debug: msg="111"
    when: ansible_distribution_major_version == "7"

因为rh2的系统是RHEL8,所以不会执行此task1,即不会显示111。

[blab@rh1 demo3]$ ansible-playbook when-1.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [task1] ******************************************************************************************
skipping: [rh2]

PLAY RECAP ********************************************************************************************
rh2                        : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

注意:ansible_distribution major version的值是一个字符串,所以when判断中=后面的7是要加引号的。

修改when-2.yaml 的内容如下。

[blab@rh1 demo3]$ cat when-2.yaml 
---
- hosts: rh2
  tasks:
  - name: task2
    debug: msg="111"
    when: ansible_distribution_major_version == "8"    

再次运行此playbook,命令如下,会显示111。

[blab@rh1 demo3]$ ansible-playbook when-2.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [task2] ******************************************************************************************
ok: [rh2] => {
    "msg": "111"
}

PLAY RECAP ********************************************************************************************
rh2                        : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

再次提醒:在when 中引用变量时是不用加{{}}的。

1.2 when判断中in的用法

在when语句中,除可以使用上面的大于、小于等判断方法外,还可以使用 in,用法如下。

value in 列表

如果此值在这个列表中,则判断成立,否则不成立。

判断某值是否在列表中,编写 when-3.yaml,命令如下。

[blab@rh1 demo3]$ cat when-3.yaml 
---
- hosts: rh2
  vars:
   list1: [1,2,3,4]
  tasks:
  - name: tasks3
    debug: msg="333"
    when: 2 in list1

此处定义了一个列表 list1,里面有4个值,分别为1、2、3、4;定义了一个task打印333,会不会执行这个task,就要看when后面的判断是否成立。如果2在列表list1中,则执行;如果不在,则不执行,很明显2在列表list1中,所以会执行此task,即屏幕上会显示333。运行结果如下。

[blab@rh1 demo3]$ ansible-playbook when-3.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [tasks3] *****************************************************************************************
ok: [rh2] => {
    "msg": "333"
}

PLAY RECAP ********************************************************************************************
rh2                        : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

因为2在列表list1中,when判断成立,可以正确执行task3,所以屏幕上会显示333。修改when-3.yaml的内容如下。

[blab@rh1 demo3]$ cat when-3.yaml 
---
- hosts: rh2
  vars:
   list1: [1,2,3,4]
  tasks:
  - name: tasks3
    debug: msg="333"
    when: 2 not in list1

这里判断的是2不在列表list1中,但2是在列表list1中的,所以判断不成立。运行结果如下 。

[blab@rh1 demo3]$ ansible-playbook  when-3.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [tasks3] *****************************************************************************************
skipping: [rh2]

PLAY RECAP ********************************************************************************************
rh2                        : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

因为when判断不成立,所以屏幕上不会显示333。

1.3when判断中is的用法

is可以用于判断变量是否被定义,常见的判断包括以下3种。
(1)is defined:变量被定义。
(2)is undefined:等同于is not defined,变量没有被定义。
(3)is none:变量被定义了,但是值为空。

看下面的例子。

[blab@rh1 demo3]$ cat when-4.yaml 
---
- hosts: rh2
  vars:
    aa: 1
    bb: 2
  tasks:
  - name: tasks1
    debug: msg="111"
    when: aa is undefined
  - name: tasks2
    debug: msg="222"
    when: bb is undefined
  - name: tasks3
    debug: msg="333"
    when: cc is not defined    

首先定义了两个变量:aa和 bb,其中bb的值为空,此处并没有定义cc。后面定义了以下3个task。

(1)如果aa被定义了,则显示111,这里aa被定义了,所以判断成立,会执行task1。
(2)如果b没有被定义,则显示222,这里bb被定义了,所以判断不成立,不会执行
task2。
(3)如果cc没有被定义,则显示333,这里cc没有被定义,所以判断成立,会执行task3。

这里is undefined 和is not defined是一个意思。

查看运行的结果,如下所示。

[blab@rh1 demo3]$ ansible-playbook  when-4.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [tasks1] *****************************************************************************************
skipping: [rh2]

TASK [tasks2] *****************************************************************************************
skipping: [rh2]

TASK [tasks3] *****************************************************************************************
ok: [rh2] => {
    "msg": "333"
}

PLAY RECAP ********************************************************************************************
rh2                        : ok=2    changed=0    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   

写一个playbook,内容如下

[blab@rh1 demo3]$ cat when-5.yaml 
---
- hosts: rh2
  tasks:
  - name: 执行一个系统命令
    shell: "ls /aa.txt"
    register: aa
    ignore_errors: yes
  - name: task2
    fail: msg=命令执行错误"001"
    when: aa.rc !=0
  - name: task3
    debug: msg="OK123"

运行此playbook命令如下

[blab@rh1 demo3]$ ansible-playbook  when-5.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [执行一个系统命令] ***************************************************************************************
fatal: [rh2]: FAILED! => {"changed": true, "cmd": "ls /aa.txt", "delta": "0:00:00.026949", "end": "2023-12-25 12:06:42.484375", "msg": "non-zero return code", "rc": 2, "start": "2023-12-25 12:06:42.457426", "stderr": "ls: 无法访问'/aa.txt': 没有那个文件或目录", "stderr_lines": ["ls: 无法访问'/aa.txt': 没有那个文件或目录"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [task2] ******************************************************************************************
fatal: [rh2]: FAILED! => {"changed": false, "msg": "命令执行错误\"001\""}

PLAY RECAP ********************************************************************************************
rh2                        : ok=2    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=1   

2.判断语句block-rescue

对于when来说,只能做一个判断,成立就执行,不成立就不执行。block和rescue一般同用,类似于shell判断语句中的if-else,在block下面可以包含多个模块,来判断这多个模块是否执行成功了。

block-rescue的用法如下。

block:
 ‐ 模块1
 ‐ 模块2
 ‐ 模块3
 rescue:
 ‐ 模块1
 ‐ 模块2

先执行 block中的模块1,如果没有报错,则继续执行模块2,如果block中的所有模块都执行成功了,则跳过rescue 中的所有模块,直接执行下一个task中的模块。

如果 block中的任一模块执行失败,block中其他后续的模块都不再执行,然后会跳转执行rescue 中的模块。

如果rescue中的某个模块执行失败,则退出整个playbook。

果某个报错模块有 ignore_errors: yes选项,则会忽略此模块的错误,继续执行下一个模块。

按上面的描述写一个playbook,内容如下。


[blab@rh1 demo3]$ cat block-1.yaml 
---
- hosts: rh2
  tasks:
  - name: task1
    block:
    - name: 11
      debug: msg="1111"

    - name: 22
      shell: "ls /aa.txt"

    - name: 33
      debug: msg="3333"

    rescue:
    - name: xx
      debug: msg="xxxx"
     
    - name: yy
      debug: msg="yyyy"

    - name: task2
      debug: msg="zzzz"    

这里在task1的block中运行了3个模块,第一个模块可以正确执行,第二个模块是执行一个系统命令ls /aa.txt,但是在rh2中是不存在/aa.txt这个文件的,所以这个模块会执行失败。block中的第三个模块不再执行,直接跳转到rescue中的模块。rescue中的2个模块均可正确执行,然后执行task2。

所以,屏幕上会显示1111, xxxx, yyyy, zzzz。运行结果如下。

[blab@rh1 demo3]$ ansible-playbook block-1.yaml 

PLAY [rh2] ********************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]

TASK [debug] ******************************************************************************************
ok: [rh2] => {
    "msg": "1111"
}

TASK [shell] ******************************************************************************************
fatal: [rh2]: FAILED! => {"changed": true, "cmd": "ls /aa.txt", "delta": "0:00:00.003160", "end": "2023-12-25 12:26:52.434462", "msg": "non-zero return code", "rc": 2, "start": "2023-12-25 12:26:52.431302", "stderr": "ls: 无法访问'/aa.txt': 没有那个文件或目录", "stderr_lines": ["ls: 无法访问'/aa.txt': 没有那个文件或目录"], "stdout": "", "stdout_lines": []}

TASK [xx] *********************************************************************************************
ok: [rh2] => {
    "msg": "xxxx"
}

TASK [yy] *********************************************************************************************
ok: [rh2] => {
    "msg": "yyyy"
}

TASK [task2] ******************************************************************************************
ok: [rh2] => {
    "msg": "zzzz"
}

PLAY RECAP ********************************************************************************************
rh2                        : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0   

你可能感兴趣的:(linux,服务器,ansible,运维)