- A+
一: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}}"
过滤器等
三:总结
when判断有很多的方式来进行判断,facts变量,注册变量,in判断等等
还有几个关键字,block,rescue,always,fail,failed_when
循环语句,最常用的就是loop循环