工程造价信息网站,数字短链接生成,Wordpress按钮添加跳转,微信如何引流推广精准加人本章内容主要介绍 playbook 中的控制语句
使用when判断语句block-rescue判断循环语句 一个play中可以包含多个task#xff0c;如果不想所有的task全部执行#xff0c;可以设置只有满足某个条件才执行这个task#xff0c;不满足条件则不执行此task。本章主要讲解when 和 blo…本章内容主要介绍 playbook 中的控制语句
使用when判断语句block-rescue判断循环语句 一个play中可以包含多个task如果不想所有的task全部执行可以设置只有满足某个条件才执行这个task不满足条件则不执行此task。本章主要讲解when 和 block-rescue两种判断语句。 1.when判断语句 when作为一个判断语句出现在某个 task下格式如下。 1 tasks : 2 ‐ name : aa 3 模块 1 4 when : 条件 1 如果条件1成立则执行模块1否则不执行。 注意 在when中引用变量时是不用加{{}}的。 本章实验都在/home/duan/demo3下操作先把 demo3目录创建出来并把ansible.cfg 和 hosts拷贝进去命令如下。 [blabnode01 ~]$ mkdir demo3
[blabnode01 ~]$ cp ansible.cfg hosts demo3/
[blabnode01 ~]$ cd demo3
[blabnode01 demo3]$
1.1when判断中! 的使用
练习1写一个playbook判断某条件是否成立成立了才执行task否则不执行命令如下。
[blabnode01 demo3]$ cat when1.yml
---
- hosts: node02tasks:- name: task1debug: msg111when: 1 2
[blabnode01 demo3]$ 这里有一个task判断12是否成立如果成立则执行task1屏幕上会显示111;如果不成立则不执行taskl屏幕上不会显示111。这里明显是成立的所以会执行task1。运行结果如下。
[blabnode01 demo3]$ ansible-playbook when1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task1] *******************************************************************
ok: [node02] {msg: 111
}PLAY RECAP *********************************************************************
node02 : ok2 changed0 unreachable0 failed0 skipped0 rescued0 ignored0 [blabnode01 demo3]$ when后面可以有多个条件用or或and作为连接符。 如果用or作为连接符,只要有一个条件成立即可只有所有的条件都不成立时,整体才不成立 练习2修改when1.yml的内容如下。
[blabnode01 demo3]$ cat when1.yml
---
- hosts: node02tasks:- name: task1debug: msg111when: 1 2 or 23
[blabnode01 demo3]$ 此处用or作为连接符只要有一个条件成立就会成立23不成立但是12成立所以整体上就是成立的。运行结果如下。 [blabnode01 demo3]$ ansible-playbook when1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task1] *******************************************************************
ok: [node02] {msg: 111
}PLAY RECAP *********************************************************************
node02 : ok2 changed0 unreachable0 failed0 skipped0 rescued0 ignored0 [blabnode01 demo3]$ 仍然会执行task1。 练习3修改when1.yml的内容如下。
[blabnode01 demo3]$ cat when1.yml
---
- hosts: node02tasks:- name: task1debug: msg111when: 12 or 23
[blabnode01 demo3]$ 此处用or作为连接符12不成立且23也不成立所以整体上就是不成立的不会执行 task1。运行结果如下。 [blabnode01 demo3]$ ansible-playbook when1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task1] *******************************************************************
skipping: [node02]PLAY RECAP *********************************************************************
node02 : ok1 changed0 unreachable0 failed0 skipped1 rescued0 ignored0 [blabnode01 demo3]$ 也可以用and作为连接符如果用and作为连接符需要所有条件全部成立只要有一个条件不成立整体上就是不成立的。 练习4修改when1.yml的内容如下。
[blabnode01 demo3]$ cat when1.yml
---
- hosts: node02tasks:- name: task1debug: msg111when: 21 and 23
[blabnode01 demo3]$ 这里虽然21是成立的但是23不成立所以整体上就是不成立的因为用and作为连接符,需要所有的条件都成立才可以所以不会执行task1。运行结果如下。 [blabnode01 demo3]$ ansible-playbook when1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task1] *******************************************************************
skipping: [node02]PLAY RECAP *********************************************************************
node02 : ok1 changed0 unreachable0 failed0 skipped1 rescued0 ignored0 [blabnode01 demo3]$ 在判断中or 和 and是可以混用的为了看得更清晰可以使用小括号。 练习5修改 when1.yml 的内容如下。 [blabnode01 demo3]$ cat when1.yml
---
- hosts: node02tasks:- name: task1debug: msg111when: (12 or 2!1) and 23
[blabnode01 demo3]$ 这里(12 or 2!1)作为一个整体12不成立但是2!1(是不等于的意思成立,所以此处( 12 or 2!1)作为一个整体是成立的。and后面23不成立所以整个when后面的判断是不成立的不会执行此 task1。运行结果如下。 [blabnode01 demo3]$ ansible-playbook when1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task1] *******************************************************************
skipping: [node02]PLAY RECAP *********************************************************************
node02 : ok1 changed0 unreachable0 failed0 skipped1 rescued0 ignored0 [blabnode01 demo3]$ 常见的判断符包括以下6种 等于!不等于大于大于等于小于小于等于 练习6如果node02的系统主版本是7(RHEL/CentOS7)则打印111否则不打印。playbook的内容如下。 [blabnode01 demo3]$ cat when2.yml
---
- hosts: node02tasks:- name: task2debug: msg222when: ansible_distribution_major_version 7
[blabnode01 demo3]$ 因为node02的系统是RHEL8所以不会执行此task2即不会显示222。 [blabnode01 demo3]$ ansible-playbook when2.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task2] *******************************************************************
skipping: [node02]PLAY RECAP *********************************************************************
node02 : ok1 changed0 unreachable0 failed0 skipped1 rescued0 ignored0 [blabnode01 demo3]$ 注意 ansible_distribution major version的值是一个字符串所以when判断中后面的7是要加引号的。 练习7修改when2.yml 的内容如下。 [blabnode01 demo3]$ cat when2.yml
---
- hosts: node02tasks:- name: task2debug: msg222when: ansible_distribution_major_version 8
[blabnode01 demo3]$ 再次运行此playbook,命令如下,会显示222。 [blabnode01 demo3]$ ansible-playbook when2.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task2] *******************************************************************
ok: [node02] {msg: 222
}PLAY RECAP *********************************************************************
node02 : ok2 changed0 unreachable0 failed0 skipped0 rescued0 ignored0 [blabnode01 demo3]$ 再次提醒在when 中引用变量时是不用加{{}}的。 1.2 when判断中in的用法 在when语句中除可以使用上面的大于、小于等判断方法外还可以使用 in用法如下。 value in 列表 如果此值在这个列表中,则判断成立否则不成立。 练习判断某值是否在列表中编写 when3.yaml命令如下。 [blabnode01 demo3]$ cat when3.yml
---
- hosts: node02vars:list1: [1,2,3,4]tasks:- name: task3debug: msg333when: 2 in list1
[blabnode01 demo3]$ 此处定义了一个列表 list1里面有4个值分别为1、2、3、4;定义了一个task打印333会不会执行这个task就要看when后面的判断是否成立。如果2在列表list1中则执行;如果不在则不执行很明显2在列表list1中所以会执行此task即屏幕上会显示333。运行结果如下。 [blabnode01 demo3]$ ansible-playbook when3.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task3] *******************************************************************
ok: [node02] {msg: 333
}PLAY RECAP *********************************************************************
node02 : ok2 changed0 unreachable0 failed0 skipped0 rescued0 ignored0 [blabnode01 demo3]$ 因为2在列表list1中when判断成立可以正确执行task3所以屏幕上会显示333。修改when-3.yaml的内容如下。 [blabnode01 demo3]$ cat when3.yml
---
- hosts: node02vars:list1: [1,2,3,4]tasks:- name: task3debug: msg333when: 2 not in list1 //增加not
[blabnode01 demo3]$ 这里判断的是2不在列表list1中但2是在列表list1中的所以判断不成立。运行结果如下。 [blabnode01 demo3]$ ansible-playbook when3.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task3] *******************************************************************
skipping: [node02]PLAY RECAP *********************************************************************
node02 : ok1 changed0 unreachable0 failed0 skipped1 rescued0 ignored0 [blabnode01 demo3]$ 因为when判断不成立所以屏幕上不会显示333。回想前面的例子。 ‐‐‐‐ hosts: dbtasks:‐ name: 打印我在清单文件中的名称debug: msg{{inventory_hostname}}when: inventory_hostname in groups [xx] 这里判断当前正在执行的主机是不是属于主机组xx,如果是则执行debug,如果不是则不执行。 1.3 when判断中is的用法
is可以用于判断变量是否被定义常见的判断包括以下3种
is defined变量被定义is undefined等同于is not definend变量没有被定义is none变量被定义了但是值为空
看下面的例子
[blabnode01 demo3]$ cat when4.yml
---
- hosts: node02vars:aa: 1bb: tasks:- name: task1debug: msg111when: aa is undefined- name: task2debug: msg222when: bb is undefined- name: task3debug: msg333when: cc is not defined
[blabnode01 demo3]$ 首先定义了两个变量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是一个意思。 查看运行的结果,如下所示。 [blabnode01 demo3]$ ansible-playbook when4.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task1] *******************************************************************
skipping: [node02]TASK [task2] *******************************************************************
skipping: [node02]TASK [task3] *******************************************************************
ok: [node02] {msg: 333
}PLAY RECAP *********************************************************************
node02 : ok2 changed0 unreachable0 failed0 skipped2 rescued0 ignored0 [blabnode01 demo3]$ 练习写一个playbook内容如下 [blabnode01 demo3]$ cat when5.yml
---
- hosts: node02tasks:- name: 执行一个系统命令shell: ls /aa.txtregister: aaignore_errors: yes- name: task2fail: msg命令执行错了001when: aa.rc ! 0- name: task3debug: msgOK001[blabnode01 demo3]$ 运行此playbook命令如下 [blabnode01 demo3]$ ansible-playbook when5.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [执行一个系统命令] ****************************************************************
fatal: [node02]: FAILED! {changed: true, cmd: ls /aa.txt, delta: 0:00:00.004728, end: 2023-12-22 10:18:56.684797, msg: non-zero return code, rc: 2, start: 2023-12-22 10:18:56.680069, stderr: ls: 无法访问/aa.txt: 没有那个文件或目录, stderr_lines: [ls: 无法访问/aa.txt: 没有那个文件或目录], stdout: , stdout_lines: []}
...ignoringTASK [task2] *******************************************************************
fatal: [node02]: FAILED! {changed: false, msg: 命令执行错了001}PLAY RECAP *********************************************************************
node02 : ok2 changed1 unreachable0 failed1 skipped0 rescued0 ignored1 [blabnode01 demo3]$ 2.判断语句block-rescue 对于when来说只能做一个判断成立就执行不成立就不执行。block和rescue一般同用,类似于shell判断语句中的if-else在block下面可以包含多个模块来判断这多个模块是否执行成功了。 block-rescue的用法如下。 1 block : 2 ‐ 模块 1 3 ‐ 模块 2 4 ‐ 模块 3 5 rescue : 6 ‐ 模块 1 7 ‐ 模块 2 先执行 block中的模块1如果没有报错则继续执行模块2如果block中的所有模块都执行成功了则跳过rescue 中的所有模块直接执行下一个task中的模块如图32-1所示 这里有2个task : task1和 task2在 task1的block中有3个模块rescue中有2个模块。如果 block1中的所有模块都正确执行了则不执行rescue中的模块直接执行task2。 如果 block中的任一模块执行失败block中其他后续的模块都不再执行,然后会跳转执行 rescue 中的模块如图32-2所示。 这里block1中的模块1执行完成之后会执行模块2如果模块2报错则不会执行模块3直接跳转到rescue中执行模块x。rescue中的所有模块全部正确执行完成之后,则执行task2。 如果rescue中的某个模块执行失败则退出整个playbook如图32-3所示。 这里 block中的模块2执行失败则跳转到rescue中执行模块x如果模块x执行失败,则退出整个 playbook,即也不会执行task2了。 如果某个报错模块有 ignore_errors: yes选项则会忽略此模块的错误继续执行下一个模块,如图32-4所示。 这里block中的模块2执行失败了但是因为加了ignore_errors: yes选项所以会忽略这个报错模块,继续执行模块3。 练习1按上面的描述写一个playbook内容如下。 [blabnode01 demo3]$ cat block1.yml
---
- hosts: node02tasks:- name: task1block:- name: 11debug: msg111- name: 22shell: ls /aa.txt- name: 33debug: msg333rescue:- name: xxdebug: msgxxxx- name: yydebug: msgyyy- name: task2debug: msgzzz[blabnode01 demo3]$ 这里在task1的block中运行了3个模块第一个模块可以正确执行第二个模块是执行一个系统命令ls /aa.txt但是在server2中是不存在/aa.txt这个文件的所以这个模块会执行失败。block中的第三个模块不再执行直接跳转到rescue中的模块。rescue中的2个模块均可正确执行然后执行task2。 所以屏幕上会显示1111, xxxx, yyyy, zzzz。运行结果如下。 [blabnode01 demo3]$ ansible-playbook block1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [debug] *******************************************************************
ok: [node02] {msg: 111
}TASK [shell] *******************************************************************
fatal: [node02]: FAILED! {changed: true, cmd: ls /aa.txt, delta: 0:00:00.006491, end: 2023-12-22 10:51:59.038337, msg: non-zero return code, rc: 2, start: 2023-12-22 10:51:59.031846, stderr: ls: 无法访问/aa.txt: 没有那个文件或目录, stderr_lines: [ls: 无法访问/aa.txt: 没有那个文件或目录], stdout: , stdout_lines: []}TASK [xx] **********************************************************************
ok: [node02] {msg: xxxx
}TASK [yy] **********************************************************************
ok: [node02] {msg: yyy
}TASK [task2] *******************************************************************
ok: [node02] {msg: zzz
}PLAY RECAP *********************************************************************
node02 : ok5 changed0 unreachable0 failed0 skipped0 rescued1 ignored0 [blabnode01 demo3]$ 练习2 修改block1.yml的内容如下。 [blabnode01 demo3]$ cat block1.yml
---
- hosts: node02tasks:- name: task1block:- name: 11debug: msg111- name: 22shell: ls /aa.txtignore_errors: yes //增加内容- name: 33debug: msg333rescue:- name: xxdebug: msgxxxx- name: yydebug: msgyyy- name: task2debug: msgzzz[blabnode01 demo3]$ 与上面的例子相比在 block的第二个模块中增加了一个 ignore_errors: yes选项这样block中的第二个模块即使报错了也会忽略这个报错继续执行第三个模块。然后执行task2,所以屏幕上会显示1111,3333,zzzz。运行结果如下。 [blabnode01 demo3]$ ansible-playbook block1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [debug] *******************************************************************
ok: [node02] {msg: 111
}TASK [shell] *******************************************************************
fatal: [node02]: FAILED! {changed: true, cmd: ls /aa.txt, delta: 0:00:00.003277, end: 2023-12-22 10:55:41.477248, msg: non-zero return code, rc: 2, start: 2023-12-22 10:55:41.473971, stderr: ls: 无法访问/aa.txt: 没有那个文件或目录, stderr_lines: [ls: 无法访问/aa.txt: 没有那个文件或目录], stdout: , stdout_lines: []}
...ignoringTASK [debug] *******************************************************************
ok: [node02] {msg: 333
}PLAY RECAP *********************************************************************
node02 : ok4 changed1 unreachable0 failed0 skipped0 rescued0 ignored1 [blabnode01 demo3]$ 3.循环语句 在shell中 for循环的用法如下。 1 for i in A B C ... ; do
2 命令 $
3 done 这里首先把A赋值给i执行do和done之间的命令;然后把B赋值给i执行do和 done之间的命令以此类推直到把in后面所有的值执行完毕。for后面的变量可以随便命名。 再回顾一下前面介绍的列表如下所示。 employee:‐ uname: lisiage: 22sex: man‐ uname: wangwuage: 24sex: man‐ uname: xiaohuaage: 21 这里列表employee中有3个元素分别记录了lisi、wangwu、xiaohua的信息。我们把这3个元素当成刚讲的for循环中的A、B、C。先把第一个元素赋值给变量执行某个操作完成之后再把第二个元素赋值给变量。 用for循环A、B、C在playbook中用loop来循环列表中的元素。在for循环中,指定一个变量如i然后分别把A、B、C赋值给i。 在loop中使用一个固定的变量 item然后把每个元素赋值给item如图32-5所示。第二次循环如图32-6所示。 练习1定义一个列表users然后循环这个列表中的每个元素,命令如下。 [blabnode01 demo3]$ cat loop1.yml
---
- hosts: node02vars:users:- uname: tomage: 20sex: man- uname: bobage: 22sex: man- uname: maryage: 19sex: womantasks:- name: task1debug: msg{{item}}loop: {{users}}
[blabnode01 demo3]$ 这里定义了一个列表users里面包含了3个用户的信息在taskl中用loop开始循环这个列表。loop后面写列表名时需要使用引号引起来这里的关键字loop可以换成关键字 with_items 这里首先把users的第一个元素赋值给item用debug 打印;然后把users的第二个元素赋值给item,用 debug打印,直到把所有的元素都赋值给 item。 运行此 playbook命令如下。 [blabnode01 demo3]$ ansible-playbook loop1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task1] *******************************************************************
ok: [node02] (item{uname: tom, age: 20, sex: man}) {msg: {age: 20,sex: man,uname: tom}
}
ok: [node02] (item{uname: bob, age: 22, sex: man}) {msg: {age: 22,sex: man,uname: bob}
}
ok: [node02] (item{uname: mary, age: 19, sex: woman}) {msg: {age: 19,sex: woman,uname: mary}
}PLAY RECAP *********************************************************************
node02 : ok2 changed0 unreachable0 failed0 skipped0 rescued0 ignored0 [blabnode01 demo3]$ 如果不想打印每个元素的所有条目只想打印每个元素的uname呢?答案:可以通过练习2 解决 练习2修改loop1.yml的内容如下。 [blabnode01 demo3]$ cat loop1.yml
---
- hosts: node02vars:users:- uname: tomage: 20sex: man- uname: bobage: 22sex: man- uname: maryage: 19sex: womantasks:- name: task1debug: msg{{item.uname}} //增加内容loop: {{users}}
[blabnode01 demo3]$ 列表的每个元素都是一个字典所以 item就是字典要获取这个字典中的uname变量,用 item.uname即可。 运行此 playbook [blabnode01 demo3]$ ansible-playbook loop1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task1] *******************************************************************
ok: [node02] (item{uname: tom, age: 20, sex: man}) {msg: tom
}
ok: [node02] (item{uname: bob, age: 22, sex: man}) {msg: bob
}
ok: [node02] (item{uname: mary, age: 19, sex: woman}) {msg: mary
}PLAY RECAP *********************************************************************
node02 : ok2 changed0 unreachable0 failed0 skipped0 rescued0 ignored0 [blabnode01 demo3]$ 练习3如果想打印所有性别为男的那些用户名修改loop1.yml 。 [blabnode01 demo3]$ cat loop1.yml
---
- hosts: node02vars:users:- uname: tomage: 20sex: man- uname: bobage: 22sex: man- uname: maryage: 19sex: womantasks:- name: task1debug: msg{{item.uname}}when: item.sex man //增加条件loop: {{users}}
[blabnode01 demo3]$ 在此playbook中我们用when加了一个判断。循环列表时首先把第一个元素赋值给item然后判断item.sex的值是否为man如果是则判断成立执行debug模块;如果不是则判断不成立,不执行debug模块。 第一次循环结束之后开始第二次循环把第二个元素赋值给item之后做相同的判断。运行此 playbook命令如下。 [blabnode01 demo3]$ ansible-playbook loop1.yml PLAY [node02] ******************************************************************TASK [Gathering Facts] *********************************************************
ok: [node02]TASK [task1] *******************************************************************
ok: [node02] (item{uname: tom, age: 20, sex: man}) {msg: tom
}
ok: [node02] (item{uname: bob, age: 22, sex: man}) {msg: bob
}
skipping: [node02] (item{uname: mary, age: 19, sex: woman}) PLAY RECAP *********************************************************************
node02 : ok2 changed0 unreachable0 failed0 skipped0 rescued0 ignored0 [blabnode01 demo3]$ 这样就把所有性别为男的用户名打印出来了。