百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

「Ansible专栏」Ansible条件判断的介绍和使用

off999 2025-03-11 19:48 31 浏览 0 评论


前言

很多时候,某些场景下playbook的结果依赖于变量、fact或者是前一个任务的执行结果,或者有的时候,我们会基于上一个task执行返回的结果而决定如何执行后续的task。这个时候就需要用到条件判断。

条件语句在Ansible中的使用场景:

  • 在目标主机上定义了一个硬限制,比如:目标主机的发行版本必须是RedHat,才能执行该task;
  • 捕获一个命令的输出,根据命令输出结果的不同以触发不同的task;
  • 根据不同目标主机的facts,以定义不同的task;
  • 根据目标机的cpu或者memory的大小,对相关应用性能进行调优;
  • 用于判断某个服务的配置文件是否发生变更,以确定是否需要重启服务等。

下面就介绍一些常用的条件判断

when 关键字

1. when 关键字使用

在ansible中,when是条件判断的最常用关键字。如在安装包的时候,需要指定主机的操作系统类型,可以使用when语句来做判断。when关键字后面跟着的是python的表达式,在表达式中你能够使用任何的变量或者fact,当表达式的结果返回的是false,便会跳过本次的任务。

示例:

---
- name: install wget package
hosts: all
tasks:
- name: Install wget
yum:
name: wget
state: installed
when: ansible_os_family == "RedHat"

2. when 配合比较运算符

以上示例,我们使用了"=="的比较运算符,在ansible中,还支持如下比较运算符:

  • ==:比较两个对象是否相等,相等则返回真。可用于比较字符串和数字
  • !=:比较两个对象是否不等,不等则为真。
  • :比较两个对象的大小,左边的值大于右边的值,则为真

  • <:比较两个对象的大小,左边的值小于右边的值,则为真
  • =:比较两个对象的大小,左边的值大于等于右边的值,则为真

  • <=:比较两个对象的大小,左边的值小于等于右边的值,则为真

如:

when: ansible_disibution == "CentOS"

when: ansible_machine == "x86_64"

when: max_memory <= 512

3. 逻辑运算符

  • and:逻辑与,当左边和右边两个表达式同时为真,则返回真
  • or:逻辑或,当左右和右边两个表达式任意一个为真,则返回真
  • not:逻辑否,对表达式取反
  • ():当一组表达式组合在一起,形成一个更大的表达式,组合内的所有表达式都是逻辑与的关系
# 逻辑与
when: ansible_disibution == "CentOS" and ansible_disibution_major_vsion == "7"

# 逻辑或
when: ansible_disibution == "RedHat" or ansible_disibution == "Fedora"

when:
- ansible_disibution_vsion == "7.9"
- ansible_kernel == "3.10.0-327.el7.x86_64"

# 组合使用
when: =>
( ansible_disibution == "RedHat" and ansible_disibution_major_vsion == "7" )
or
( ansible_disibution == "Fedora" and ansible_disibution_major_vsion == "28")

示例:

- name: uninstall and stop forewalld
hosts: dbsrvs
tasks:
- name: uninstall firewalld
yum: pkg=firwalld state=absent
when: ansible_disibution == "CentOS" and ansible_disibution_major_vsion == "7"
tags: uninstall_firewalld

- name: stop and disabled iptables
shell: systemctl stop firewalld.service && systemctl disable firewalld && systemctl stop iptables && systemctl disable iptables
when: ansible_disibution == "CentOS" and ansible_disibution_major_vsion == "7"
tags: stop_firewalld

###
- name: restart httpd if postfix is running
hosts: dbsrvs
tasks:
- name: get postfix serv status
command: /usr/bin/systemctl is-active postfix
ignore_errors: yes
register: result

- name: restart apache httpd based on postfix status
service:
name: httpd
state: restarted
when: result.rc == 0

tests 配合条件判断

通过条件语句判断tpath的路径是否存在

- hosts: dbsrvs
vars:
tpath: /ayunwSky
tasks:
- debug:
msg: "file exist"
when: tpath is exists

参数解释:

  • is exists: 用于路径存在时返回真
  • is not exists: 用于路径不存在时返回真

    • 也可以在整个条件表达式的前面使用not来取反
- hosts: dbsrvs
vars:
tpath: /ayunwSky
tasks:
- debug:
msg: "file not exist"
when: not tpath is exists

除了 exists 方式以外,还有其他的判断方式,如下:

判断变量
  • defined:判断变量是否已定义,已定义则返回真
  • undefined:判断变量是否未定义,未定义则返回真
  • none:判断变量的值是否为空,如果变量已定义且值为空,则返回真
- hosts: dbsrvs
gather_facts: no
vars:
tvar: "test"
tvar1:
tasks:
- debug:
msg: "tvar is defined"
when: tvar is defined
- debug:
msg: "tvar2 is undefined"
when: tvar2 is undefined
- debug:
msg: "tvar1 is none"
when: tvar1 is none

判断执行结果

  • sucess或succeeded:通过任务执行结果返回的信息判断任务的执行状态,任务执行成功则返回true
  • failure或failed:任务执行失败则返回true
  • change或changed:任务执行状态为changed则返回true
  • skip或skipped:任务被跳过则返回true
- hosts: dbsrvs
gather_facts: no
vars:
doshell: true
tasks:
- shell: 'cat /ayunwSky/allenjol'
when: doshell
register: result
ignore_errors: true
- debug:
msg: "success"
when: result is success

- debug:
msg: "failed"
when: result is failure

- debug:
msg: "changed"
when: result is change

- debug:
msg: "skip"
when: result is skip

判断路径

  • file:判断指定路径是否为一个文件,是则为真
  • directory:判断指定路径是否为一个目录,是则为真
  • link:判断指定路径是否为一个软链接,是则为真
  • mount:判断指定路径是否为一个挂载点,是则为真
  • exists:判断指定路径是否存在,存在则为真

关于路径的所有判断均是判断主控端上的路径,而非被控端上的路径

- hosts: dbsrvs
gather_facts: no
vars:
tpath1: "/ayunwSky/allenjol"
tpath2: "/ayunwSky"
tasks:
- debug:
msg: "file"
when: tpath1 is file
- debug:
msg: "directory"
when: tpath2 is directory

判断字符串

  • lower:判断字符串中的所有字母是否都是小写,是则为真
  • upper:判断字符串中的所有字母是否都是大写,是则为真
- hosts: dbsrvs
gather_facts: no
vars:
s1: "ayunw"
s2: "AYUNW"
tasks:
- debug:
msg: "s1 is all lowercase"
when: s1 is lower
- debug:
msg: "s2 is all uppercase"
when: s2 is upper

判断整除

  • even:判断数值是否为偶数,是则为真
  • odd:判断数值是否为奇数,是则为真
  • divisibleby(n):判断是否可以整除指定的数值,是则为真
- hosts: dbsrvs
gather_facts: no
vars:
n1: 5
n2: 10
n3: 20
tasks:
- debug:
msg: "n1 is an even nber"
when: n1 is even
- debug:
msg: "n2 is an odd nber"
when: n2 is odd
- debug:
msg: "n3 can be divided exactly by"
when: n3 is divisibleby(3)

其他 tests 方法

  1. version:对比两个版本号的大小,或者与指定的版本号进行对比,使用语法为vsion("版本号","比较操作符")

version中使用的比较运算符说明:

  • 大于:>, gt
  • 大于等于:>=, ge
  • 小于:<, lt
  • 小于等于:<=, le
  • 等于:=, ==, eq
  • 不等于:!=, <>, ne
- hosts: dbsrvs
vars:
v1: 1.2
v2: 1.3
tasks:
- debug:
msg: "v1 is greater than v2"
when: v1 is vsion(v2,">")
- debug:
msg: "system vsion {{ ansible_distribution_vsion }} greater than 7.3"
when: ansible_distribution_vsion is vsion("7.3","gt")
  1. superset: 判断一个list是不是另一个list的父集
- hosts: dbsrvs
gather_facts: no
vars:
a:
- 3
- 7
b: [1,3,4,5,7,9]
tasks:
- debug:
msg: "A is a subset of B"
when: a is subset(b)
- debug:
msg: "B is the parent set of A"
when: b is superset(a)
  1. in: 判断一个字符串是否存在于另一个字符串中,也可用于判断某个特定的值是否存在于列表中
- hosts: dbsrvs
vars:
supported_distros:
- RedHat
- CentOS
tasks:
- debug:
msg: "{{ ansible_distribution }} in supported_distros"
when: ansible_distribution in supported_distros

  1. number: 判断对象是否为一个数字,是则为真
- hosts: dbsrvs
gather_facts: no
vars:
var1: 1
var2: "1"
var3: a
tasks:
- debug:
msg: "var1 is a number"
when: var1 is number
- debug:
msg: "var2 is a string"
when: var2 is string
- debug:
msg: "var3 is a string"
when: var3 is string

条件判断与block

block

when做条件判断时,如果条件成立则执行对应的任务。但这就存在一个问题:当我们要使用同一个条件判断执行多个任务的时候,就意味着我们要在某一个任务下面都写一下when语句,而且判断条件完全一样。这种方式非常麻烦。Ansible提供了一种更好的方式来解决这个问题,即block。

在ansible中,使用block将多个任务进行组合,当作一个整体。我们可以对这一个整体做条件判断,当条件成立时,则执行块中的所有任务:

使用block注意事项:

  • 可以为block定义name
  • 可以直接对block使用when,但不能直接对block使用loop
- hosts: dbsrvs
tasks:
- name: set /etc/resolv.conf
template:
src: resolv.conf.j2
dest: /etc/resolv.conf
owner: root
group: root
mode: 0644
- block:
- name: ensure /etc/resolvconf/resolv.conf.d/base file for ubuntu 16.04
template:
src: resolv.conf.j2
dest: /etc/resolvconf/resolv.conf.d/base

- name: config dns for ubuntu 16.04
template:
src: resolv.conf.j2
dest: /etc/resolv.conf
when: ansible_distribution == "Ubuntu" and ansible_distribution_major_version == "16"

rescue

block除了能和when一起使用之外,还能作错误处理。这个时候就需要用到rescue关键字:

- hosts: dbsrvs
tasks:
- block:
- shell: 'ls /ayunwSky'
rescue:
- debug:
msg: '/ayunwSky is not exists'

当block中的任务执行失败时,则运行rescue中的任务。如果block中的任务正常执行,则rescue的任务就不会被执行。如果block中有多个任务,则任何一个任务执行失败,都会执行rescue。block中可以定义多个任务,同样rescue当中也可以定义多个任务。

always

当block执行失败时,rescue中的任务才会被执行;而无论block执行成功还是失败,always中的任务都会被执行:

- hosts: dbsrvs
tasks:
- block:
- shell: 'ls /ayunwSky'
rescue:
- debug:
msg: '/ayunwSky is not exists'
always:
- debug:
msg: 'This task always executes'

条件判断与错误处理

fail模块

在shell中,可能会有这样的需求:当脚本执行至某个阶段时,需要对某个条件进行判断,如果条件成立,则立即终止脚本的运行。在shell中,可以直接调用"exit"即可执行退出。事实上,在playbook中也有类似的模块可以做这件事。即fail模块。

fail模块用于终止当前playbook的执行,通常与条件语句组合使用,当满足条件时,终止当前play的运行。

fail模块只有一个参数,即 msg:终止前打印出信息

# 使用fail模块中断playbook输出
- hosts: dbsrvs
tasks:
- shell: echo "Just a test--error"
register: result

- fail:
msg: "Conditions established,Interrupt running playbook"
when: "'error' in result.stdout"

- debug:
msg: "Inever execute,Because the playbook has stopped"

failed_when

当fail和when组合使用的时候,还有一个更简单的写法,即failed_when,当满足某个条件时,ansible主动触发失败。

如果在command_result存在错误输出,且错误输出中,包含了FAILED字串,即返回失败状态:

- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
failed_when: "'FAILED' in command_result.stderr"

直接通过fail模块和when条件语句:

- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
ignore_errors: True

- name: fail the play if the previous command did not succeed
fail: msg="the command failed"
when: " command_result.stderr and 'FAILED' in command_result.stderr"
  • ansible一旦执行返回失败,后续操作就会中止,所以failed_when通常可以用于满足某种条件时主动中止playbook运行的一种方式。
  • ansible默认处理错误的机制是遇到错误就停止执行。但有些时候,有些错误是计划之中的。我们希望忽略这些错误,以让playbook继续往下执行。此时可以使用ignore_errors忽略错误,从而让playbook继续往下执行。

changed_when

当我们控制一些远程主机执行某些任务时,当任务在远程主机上成功执行,状态发生更改时,会返回changed状态响应,状态未发生更改时,会返回OK状态响应,当任务被跳过时,会返回skipped状态响应。我们可以通过changed_when来手动更改changed响应状态

- shell: /usr/bin/billybass --mode="take me to the river"
register: bass_result
# 该条task执行以后,bass_result.rc的值不为2时,才会返回changed状态
changed_when: "bass_result.rc != 2"

# this will never report 'changed' status
- shell: wall 'beep'
# 当changed_when为false时,该条task在执行以后,永远不会返回changed状态
changed_when: False

循环语句中使用条件语句

  1. 只打印大于 10 的值
tasks:
- command: echo {{ item }}
loop: [ 0, 2, 4, 6, 8, 10, 100, 130, 150 ]
when: item > 10
  1. 确保将mariadb-server安装到根分区且根分区的可用空间要大于200M
- name: install nginx if enough space on root
yum:
name: nginx
state;latest
loop: "{{ ansible_mounts }}"
when: item.mount == "/" and item.size_available > 200000000

以上就是大部分的判断方法,欢迎各位志同道合的朋友一起交流。


温馨提示

一名常年穿梭于Google、阿里、百度、腾讯的一线运维从业者。是<<运维开发故事>>公众号的成员之一。不定期分享技术干货和对技术的理解与感悟。


如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我,期待与大家共同成长进步!

........................


相关推荐

中国北斗卫星导航系统(中国北斗卫星导航系统收费吗)

中国的北斗卫星是1994年开始研究的。1994年,我国启动北斗一号系统工程建设。2000年10月31日,第一颗“北斗一号”实验导航卫星升空。北斗系统至今发展共有三代,其中第一代也被称为“北斗卫星导航试...

日文图片文字识别在线(日文图片文字翻译)

将图片转换成文字,采用“ocr文字识别软件”可以实现,参考方法如下:1、打开(迅捷)文字识别软件,关闭上面的提示窗口;2、通过左上角的添加文件按钮,将需要转换的图片添加进去;3、点击开始识别按钮,开始...

祖玛传奇手机版下载(祖玛传奇手机版下载赚红包)

1.可能是因为下载链接失效或者被删除了。2.经典祖玛传奇是一款非常受欢迎的游戏,可能存在版权问题或者侵权问题,导致下载链接被删除或者失效。3.如果想要玩经典祖玛传奇,可以尝试在正规的游戏平台或者...

免费音乐剪辑软件(免费音乐编辑软件)

AdobeAudition(Windows系统和Mac系统都可以)和CoolEditPro(Windows系统)!这两款软件都是免费的,音频剪辑方面功能很全。例如:分音轨、多音轨混录、降噪、立体...

sdwan跨境专线(sdwan跨境专线个人能申请么)

SD-WAN跨境专线在合规合法方面存在一些具体的限制。在不同国家和地区的法律法规布局上存在差异,因此,跨境专线一定要遵守所在国家和地区的相关规定,例如中国的《关于规范互联网接入服务市场秩序的若干规定》...

北京科兴疫苗(北京科兴疫苗对人体的影响)

合格。国家有各种疫苗的审核标准,达到标准后才可以接种。国家不可能让不合格的疫苗,进入接种环节。这点大家可以放心!近期可能都不会有科兴的疫苗,是因为国家购入数量较少的原因。因为科兴是由北京科兴生物制品有...

阿里旺旺官网入口(阿里旺旺app官网)

阿里巴巴国际站旺旺有手机版。国际版阿里旺旺的下载地址是:http://trademanager.alibaba.com/有IOS和android版本阿里巴巴国际站是阿里巴巴集团最早创立的业务,是目前...

google地球手机版下载(google地球7.12手机版)

手机版本的还是电脑版本的呀,电脑版本的直接在谷歌的网站下载就是了,手机版本的就是在谷歌play商店下载就是了。需要告诉你的是,国内无法使用谷歌地球。可以在应用宝中下载,然后将下载好的谷歌地球导入进Ou...

windows11云电脑(在线windows云电脑)
windows11云电脑(在线windows云电脑)

关闭win11的云端服务的方法如下1.首先我们进入手机设置,然后点击我们的用户名称可以进入账号设置。2.确认信息后,点击“退出账号”即可关闭华为云空间了,如果我们只想要关闭备份功能的话,可以进入“云空间”3.接着点击其中的云备份选项进入,最...

2026-02-01 13:15 off999

诺基亚所有型号及图片(诺基亚所有型号及图片及价格)

诺基亚:N71、N73、N75、N76、N77、N78、N79、N80、N81、N81(8GB)、N82、N85、N91、N91(8GB)、N92、N93、N93i、N95、N95(8GB)、N96、...

星空视频壁纸(星空壁纸引擎)

星空视频壁纸设置方法:打开“开始”→“控制面板”→“更改桌面背景”→有个关于图片属性的,选择“填充”即可,还可以从“计算机”-----“组织”----“属性”----“控制面板”,其余重复一样的。您...

图片文字识别软件(图片文字识别软件哪个好)

华为手机自带文件扫描,打开华为手机的相机,选择左上角的那个图标,点进去之后下面会看到一个文字的图标,选择那个就可以对准文件拍照自动识别了,自己手写的也可以识别,就是精准度会根据你写的字的工整程度有影响...

新盟网上订烟草登录(新盟手机网上订烟草登录)

找你所在的管辖区域客户经理申请帐号,他会给你的。新商盟用户名是零售户的客户编码,送烟小票上有,不清楚的可以致电客户经理。初始密码是零售户开通新商盟的时候电脑系统随即分配的六位数。根据你说的情况,分析情...

电信网上营业厅入口(电信网上营业大厅)

你好,查询各地营业厅号码,只需拨打114号码百事通即可。要找到电信的营业厅,可以通过多种途径进行查询。首先,可以在电信官方网站上查找最近的营业厅地址和联系方式。其次,可以通过拨打电信客服热线100查询...

期货公司哪家手续费最便宜(正规的期货公司哪家手续费低)

华泰长城期货公司开户手续费是业内比较低的,股指开户手续费万0.275,商品期货开户在交易所基础加收30%。反正是没有手续费最低的期货公司,手续费高低是期货公司适度调节的,只要客户的成交量大,期货公司就...

取消回复欢迎 发表评论: