黑帽联盟

 找回密码
 会员注册
查看: 832|回复: 0
打印 上一主题 下一主题

[基础服务] ansible笔记(26):条件判断

[复制链接]
yun 黑帽联盟官方人员 

920

主题

37

听众

1364

积分

超级版主

Rank: 8Rank: 8

  • TA的每日心情
    奋斗
    2019-10-18 11:20
  • 签到天数: 678 天

    [LV.9]以坛为家II

    本帖最后由 yun 于 2019-9-11 17:14 编辑

    ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。
    ansible系列博文直达链接:ansible轻松入门系列
    "ansible系列"中的每篇文章都建立在前文的基础之上,所以,请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。


    之前的文章总结了大多数循环关键字的使用方法,这篇文章总结一下ansible中条件判断的用法。

    绝大多数语言中,都使用"if"作为条件判断的关键字,而在ansible中,条件判断的关键字是"when",我们来看一个简单的示例,如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - debug:
    6.       msg: "System release is centos"
    7.     when: ansible_distribution == "CentOS"
    复制代码
    如上例所示,使用when关键字指明条件,条件是ansible_distribution的值是CentOS,细心如你一定已经发现了,ansible_distribution就是facts信息中的一个key,通过ansible_distribution可以获取到目标主机系统的发行版,在之前的文章中,如果我们需要获取到facts中的key的值,都是通过引用变量的方式获取的,即"{{ key }}",但是,在使用when关键字时,我们并没有为ansible_distribution添加"{{  }}",没错,在when关键字中引用变量时,变量名不需要加"{{  }}", 那么上例playbook表示,如果ansible_distribution的值是CentOS,则调用debug模块,输出"System release is centos"这句话,如果ansible_distribution的值不是CentOS,则不满足条件,则不会调用debug模块,你肯定已经理解了,我们可以使用when关键字为任务指定条件,条件成立,则执行任务,条件不成立,则不执行任务,那么我们再来看一个用于循环的条件判断示例,如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   tasks:
    6.   - debug:
    7.       msg: "{{ item }}"
    8.     with_items:
    9.     - 1
    10.     - 2
    11.     - 3
    12.     when: item > 1
    复制代码
    上例表示当item的值大于1时,才会调用debug模块输出对应的信息,很简单吧~

    在上述两个示例中,我们使用了 "==" 和 ">" 两个比较运算符,在ansible中,我们可以使用如下比较运算符。
    ==  :比较两个对象是否相等,相等为真
    !=  :比较两个对象是否不等,不等为真
    >   :比较两个值的大小,如果左边的值大于右边的值,则为真
    <  :比较两个值的大小,如果左边的值小于右边的值,则为真
    >=  :比较两个值的大小,如果左边的值大于右边的值或左右相等,则为真
    <=  :比较两个值的大小,如果左边的值小于右边的值或左右相等,则为真
    我们总结的这些运算符其实都是jinja2的运算符,ansible使用jinja2模板引擎,在ansible中也可以直接使用jinja2的这些运算符。

    说完了比较运算符,再来说说逻辑运算符,可用的逻辑运算符如下
    and  :逻辑与,当左边与右边同时为真,则返回真
    or  :逻辑或,当左边与右边有任意一个为真,则返回真
    not  :取反,对一个操作体取反
    ( )  :组合,将一组操作体包装在一起,形成一个较大的操作体

    我们来看一些关于逻辑运算符的示例,如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - debug:
    6.       msg: "System release is centos7"
    7.     when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7"
    复制代码
    上例表示,如果想要debug模块能够输出"System release is centos7"这句话,需要同时满足两个条件,ansible_distribution的值是CentOS,同时ansible_distribution_major_version的值是7

    其实,当我们需要使用"逻辑与"时,除了使用"and"这种写法,还能够使用另一种"列表"的写法,示例如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - debug:
    6.       msg: "System release is centos7"
    7.     when:
    8.     - ansible_distribution == "CentOS"
    9.     - ansible_distribution_major_version == "7"
    复制代码
    上例的when中定义了一个列表,这个列表中的每一项都是一个条件,列表中的所有条件同时成立时,对应的任务才会执行。

    再来看一个示例,这个示例同时用到了逻辑与、逻辑或、分组组合,示例如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - debug:
    6.       msg: "System release is centos6 or centos7"
    7.     when: ansible_distribution == "CentOS" and
    8.           (ansible_distribution_major_version == "6" or ansible_distribution_major_version == "7")
    复制代码
    我就不废话了,你一定看懂了。

    还有"取反"的示例,如下示例表示如果系统的发行版不是centos,则输出"System release is not centos"这句话
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - debug:
    6.       msg: "System release is not centos"
    7.     when: not ansible_distribution == "CentOS"
    复制代码
    当我们调用shell模块运行命令时,通常需要获取到shell模块的返回信息,以便之后的模块能够根据返回信息的值判断之后进行怎样的操作,示例如下,如下示例存在一个问题,我们一起来看一下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - name: task1
    6.     shell: "ls /testabc"
    7.     register: returnmsg
    8.   - name: task2
    9.     debug:
    10.       msg: "Command execution successful"
    11.     when: returnmsg.rc == 0
    12.   - name: task3
    13.     debug:
    14.       msg: "Command execution failed"
    15.     when: returnmsg.rc != 0
    复制代码
    从上述示例可以看出我们的意图,我们想要通过shell模块在远程主机test70中执行命令 "ls /testabc",我们将shell模块的返回值注册到了变量returnmsg,然后通过returnmsg获取到了命令执行的返回码,如果返回码为0,则证明命令完全正常执行,如果返回码不为0,则证明命令执行时出错了,test70主机中其实并不存在/testabc这个文件或者目录,所以,按照理想的情况,debug模块应该会输出"Command execution failed"这句话,那么我们执行一下上例的playbook,看看执行结果与我们预想的是否相同,执行情况如下:
    1.png
    如图所示,由于远程主机中并不存在"/testabc",所以task1执行报错了,这在我们的预料之中,但是之后的task2和task3并未执行,这是因为ansible默认的机制是当playbook中的某个task执行后,如果task报错,playbook会在报错task的位置上停止,报错task之后的task则不会执行,所以,由于上例的task1报错了,palybook就停止在task1的位置了,task2和task3压根就没执行,更别说判断task1的执行结果了,那么,我们需要一种方法,即使task1执行报错,也能接着执行之后的task,以便之后的task能够获取到task1的状态,那么我们该怎么办呢?
    很简单,通过"ignore_errors"关键字即可实现这种效果,"ignore_errors"表示即使当前task执行报错,ansible也会忽略这个错误,继续执行playbook,示例如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - name: task1
    6.     shell: "ls /testabc"
    7.     register: returnmsg
    8.     ignore_errors: true
    9.   - name: task2
    10.     debug:
    11.       msg: "Command execution successful"
    12.     when: returnmsg.rc == 0
    13.   - name: task3
    14.     debug:
    15.       msg: "Command execution failed"
    16.     when: returnmsg.rc != 0
    复制代码
    如上例所示,我们为task1添加了"ignore_errors"关键字,并且设置"ignore_errors"的值为true,表示shell模块执行报错后,ansible会忽略报错,继续执行之后的task。

    到目前为止,我们总结的条件判断方法都比较简单,通常来说,当我们进行条件判断时,还能够借助一些其他的方法,这些方法会在之后的文章中进行总结吧,希望这篇文章能够对你有所帮助。

    帖子永久地址: 

    黑帽联盟 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与黑帽联盟享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和黑帽联盟的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、黑帽联盟管理员和版主有权不事先通知发贴者而删除本文

    您需要登录后才可以回帖 登录 | 会员注册

    发布主题 !fastreply! 收藏帖子 返回列表 搜索
    回顶部