黑帽联盟

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

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

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

920

主题

37

听众

1364

积分

超级版主

Rank: 8Rank: 8

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

    [LV.9]以坛为家II

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

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

    在写这篇文章时,遇到了一个小bug,经过测试,当前最新版本(2.6.2)的ansible不存在此bug,于是将ansible版本从2.4.2升级到了2.6.2,从这篇文章开始,如果没有特殊说明,演示环境中的ansible的版本为2.6.2.

    在linux中,我们可以使用test命令进行一些常用的判断操作,比如,使用test命令判断"/testdir"是否存在,示例如下
    1. # test -e /testdir
    2. # echo $?
    3. 0
    复制代码
    上述命令表示判断"/testdir"是否存在于系统中,如果"/testdir"存在,则返回true,如果"/testdir"不存在,则返回false,而在linux中,命令的返回值为0表示true,返回值为非0表示false,上例的返回值为0,所以"/testdir"存在于文件系统中,我们也可以在shell脚本中使用test命令进行判断,示例如下
    1. #!/bin/bash

    2. if test -e /testdir; then
    3.   echo "testdir exist"
    4. fi
    复制代码
    其实,在ansible中,也有类似的用法,只不过ansible没有使用linux的test命令,而是使用了jinja2的tests,借助tests,我们可以进行一些判断操作,tests会将判断后的布尔值返回,如果条件成立,则返回true,如果条件不成立,tests会返回false,我们通常会在条件判断时使用到tests,那么怎样在ansible中使用jinja2的tests进行判断呢?我们先来看一个小例子,示例如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars:
    6.     testpath: /testdir
    7.   tasks:
    8.   - debug:
    9.       msg: "file exist"
    10.     when: testpath is exists
    复制代码
    如上例所示,我们定义了一个testpath变量,这个变量的值是"/testdir"路径,我通过when判断"/testdir"路径是否存在,没错,就是这么简单,"is exists"中的"exists"就是tests的一种,它与"test -e"命令的作用是相同的,通过"exists"可以判断ansible主机中的对应路径是否存在(注意:是ansible控制主机中的路径,与目标主机没有关系),当对应的路径存在于ansible控制节点时,"is exists"为真,是不是很简单?

    "is exists"可以在路径存在时返回真,但是有时,我们想要在路径不存在时返回真,我们该怎么办呢?我们可以使用"is not exists","is not exists"表示对应路径不存在时返回真,示例如下:
    1.   vars:
    2.     testpath: /testdir1
    3.   tasks:
    4.   - debug:
    5.       msg: "file not exist"
    6.     when: testpath is not exists
    复制代码
    你一定已经明白了,在ansible中,"is exists"表示如果路径存在于ansible节点则返回真,"is not exists"表示如果路径不存在于ansible节点则返回真,当我们使用一种tests进行条件判断时,在tests前面加上"is"进行判断,也可以在tests前面加上"is not"进行取反的判断,当然,在前一篇文章中,我们已经总结了取反的逻辑操作符,所以,我们也可以对整个条件取反,比如如下示例
    1.   vars:
    2.     testpath: /testdir1
    3.   tasks:
    4.   - debug:
    5.       msg: "file not exist"
    6.     when: not testpath is exists
    复制代码
    上例取反的效果与"is not"的效果相同。

    在ansible中,除了能够使用"exists"这种tests,还有一些别的tests能够使用,我们来认识一下这些tests

    判断变量的一些tests
    defined :判断变量是否已经定义,已经定义则返回真
    undefind :判断变量是否已经定义,未定义则返回真
    none :判断变量值是否为空,如果变量已经定义,但是变量值为空,则返回真

    上述tests的使用示例如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars:
    6.     testvar: "test"
    7.     testvar1:
    8.   tasks:
    9.   - debug:
    10.       msg: "Variable is defined"
    11.     when: testvar is defined
    12.   - debug:
    13.       msg: "Variable is undefined"
    14.     when: testvar2 is undefined
    15.   - debug:
    16.       msg: "The variable is defined, but there is no value"
    17.     when: testvar1 is none
    复制代码
    当对应的条件为真时,你可以看到debug模块对应的输出。

    判断执行结果的一些tests
    success 或 succeeded:通过任务的返回信息判断任务的执行状态,任务执行成功则返回真
    failure 或 failed:通过任务的返回信息判断任务的执行状态,任务执行失败则返回真
    change 或 changed:通过任务的返回信息判断任务的执行状态,任务执行状态为changed则返回真
    skip 或 skipped:通过任务的返回信息判断任务的执行状态,当任务没有满足条件,而被跳过执行时,则返回真

    上述tests的使用示例如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars:
    6.     doshell: "yes"
    7.   tasks:
    8.   - shell: "cat /testdir/abc"
    9.     when: doshell == "yes"
    10.     register: returnmsg
    11.     ignore_errors: true
    12.   - debug:
    13.       msg: "success"
    14.     when: returnmsg is success
    15.   - debug:
    16.       msg: "failed"
    17.     when: returnmsg is failure
    18.   - debug:
    19.       msg: "changed"
    20.     when: returnmsg is change
    21.   - debug:
    22.       msg: "skip"
    23.     when: returnmsg is skip
    复制代码
    如上例所示,我们调用了shell模块,将shell模块的返回信息注册在了returnmsg变量中,之后的debug任务均通过returnmsg变量判断shell模块的执行状态,因为shell模块有可能执行失败,所以,我们为shell模块添加了"ignore_errors: true",以便即使shell模块执行失败,也能执行后面的任务,并且,我为shell模块添加了判断条件,当不满足条件时,shell模块则会跳过,即不会执行,你可以修改一下条件,以便测试skip的判断效果。

    判断路径的一些tests
    注:如下tests的判断均针对于ansible主机中的路径,与目标主机无关
    file : 判断路径是否是一个文件,如果路径是一个文件则返回真
    directory :判断路径是否是一个目录,如果路径是一个目录则返回真
    link :判断路径是否是一个软链接,如果路径是一个软链接则返回真
    mount:判断路径是否是一个挂载点,如果路径是一个挂载点则返回真
    exists:判断路径是否存在,如果路径存在则返回真
    注:上述test名均为2.6版本中的名称,在2.5版本之前某些test需要加上"is_"前缀

    上述tests的使用示例如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars:
    6.     testpath1: "/testdir/test"
    7.     testpath2: "/testdir/"
    8.     testpath3: "/testdir/testsoftlink"
    9.     testpath4: "/testdir/testhardlink"
    10.     testpath5: "/boot"
    11.   tasks:
    12.   - debug:
    13.       msg: "file"
    14.     when: testpath1 is file
    15.   - debug:
    16.       msg: "directory"
    17.     when: testpath2 is directory
    18.   - debug:
    19.       msg: "link"
    20.     when: testpath3 is link
    21.   - debug:
    22.       msg: "link"
    23.     when: testpath4 is link
    24.   - debug:
    25.       msg: "mount"
    26.     when: testpath5 is mount
    27.   - debug:
    28.       msg: "exists"
    29.     when: testpath1 is exists
    复制代码
    判断字符串的一些tests
    lower:判断包含字母的字符串中的字母是否是纯小写,字符串中的字母全部为小写则返回真
    upper:判断包含字母的字符串中的字母是否是纯大写,字符串中的字母全部为大写则返回真

    上述tests的使用示例如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars:
    6.     str1: "abc"
    7.     str2: "ABC"
    8.   tasks:
    9.   - debug:
    10.       msg: "This string is all lowercase"
    11.     when: str1 is lower
    12.   - debug:
    13.       msg: "This string is all uppercase"
    14.     when: str2 is upper
    复制代码
    判断整除的一些tests
    even :判断数值是否是偶数,是偶数则返回真
    odd :判断数值是否是奇数,是奇数则返回真
    divisibleby(num) :判断是否可以整除指定的数值,如果除以指定的值以后余数为0,则返回真

    上述tests的使用示例如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars:
    6.     num1: 4
    7.     num2: 7
    8.     num3: 64
    9.   tasks:
    10.   - debug:
    11.       msg: "An even number"
    12.     when: num1 is even
    13.   - debug:
    14.       msg: "An odd number"
    15.     when: num2 is odd
    16.   - debug:
    17.       msg: "Can be divided exactly by"
    18.     when: num3 is divisibleby(8)
    复制代码
    其他的一些testst
    version:可以用于对比两个版本号的大小,或者与指定的版本号进行对比,使用语法为 version('版本号', '比较操作符')
    注:2.5版本中此tests从version_compare更名为version

    示例如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   vars:
    5.     ver: 7.4.1708
    6.     ver1: 7.4.1707
    7.   tasks:
    8.   - debug:
    9.       msg: "This message can be displayed when the ver is greater than ver1"
    10.     when: ver is version(ver1,">")
    11.   - debug:
    12.       msg: "system version {{ansible_distribution_version}} greater than 7.3"
    13.     when: ansible_distribution_version is version("7.3","gt")
    复制代码
    上例中有两个task
    第一个task中,当ver的版本号大于ver1时,返回真,条件成立,debug模块输出"This message can be displayed when the ver is greater than ver1"
    第二个task中,当facts中的ansible_distribution_version的值大于7.3时,返回真,条件成立,debug模块输出对应信息
    细心如你一定发现了,">"与"gt"都表示"大于",当使用version时,支持多种风格的比较操作符,你可以根据自己的使用习惯进行选择,version支持的比较操作符如下
    大于:>, gt
    大于等于:>=, ge
    小于:<, lt
    小于等于:<=, le
    等于: ==, =, eq
    不等于:!=, <>, ne

    subset:判断一个list是不是另一个list的子集,是另一个list的子集时返回真
    superset : 判断一个list是不是另一个list的父集,是另一个list的父集时返回真
    注:2.5版本中上述两个tests从issubset和issuperset更名为subset和superset

    示例如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars:
    6.     a:
    7.     - 2
    8.     - 5
    9.     b: [1,2,3,4,5]
    10.   tasks:
    11.   - debug:
    12.       msg: "A is a subset of B"
    13.     when: a is subset(b)
    14.   - debug:
    15.       msg: "B is the parent set of A"
    16.     when: b is superset(a)
    复制代码
    string:判断对象是否是一个字符串,是字符串则返回真
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars:
    6.     testvar1: 1
    7.     testvar2: "1"
    8.     testvar3: a
    9.   tasks:
    10.   - debug:
    11.       msg: "This variable is a string"
    12.     when: testvar1 is string
    13.   - debug:
    14.       msg: "This variable is a string"
    15.     when: testvar2 is string
    16.   - debug:
    17.       msg: "This variable is a string"
    18.     when: testvar3 is string
    复制代码
    上例playbook中只有testvar2和testvar3会被判断成字符串,testvar1不会

    number:判断对象是否是一个数字,是数字则返回真
    示例如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars:
    6.     testvar1: 1
    7.     testvar2: "1"
    8.     testvar3: 00.20
    9.   tasks:
    10.   - debug:
    11.       msg: "This variable is number"
    12.     when: testvar1 is number
    13.   - debug:
    14.       msg: "This variable is a number"
    15.     when: testvar2 is number
    16.   - debug:
    17.       msg: "This variable is a number"
    18.     when: testvar3 is number
    复制代码
    上例playbook中只有testvar1和testvar3会被判断成数字,testvar2不会


    这篇文章就总结到这里,希望能够对你有所帮助~

    帖子永久地址: 

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

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

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