黑帽联盟

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

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

[复制链接]
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系列"中的每篇文章都建立在前文的基础之上,所以,请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。


    在前文中,我们总结了条件判断的语法,以及一些tests的使用方法,这篇文章我们再来总结一些与条件判断有关的知识点

    前文中,我们使用"when"关键字对条件进行判断,如果条件成立,则执行对应的任务,但是,细心如你一定已经发现了,当条件成立时,我们只能执行一个任务,如果我们想要在条件成立时,执行三个任务,该怎么办呢?难道我们要在这三个任务的每个任务中都加入相同的条件判断么?这种方法也太麻烦了,显然应该有更好的方法,没错,我们可以借助"block"解决这个小问题。

    在ansible中,可以使用"block"关键字将多个任务整合成一个"块",这个"块"将被当做一个整体,我们可以对这个"块"添加判断条件,当条件成立时,则执行这个块中的所有任务,我们来看一个小示例,如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - debug:
    6.       msg: "task1 not in block"
    7.   - block:
    8.       - debug:
    9.           msg: "task2 in block1"
    10.       - debug:
    11.           msg: "task3 in block1"
    12.     when: 2 > 1
    复制代码
    上例中一共包含三个任务,第一个任务使用debug模块输出了 "task1 not in block"这句话,在第一个任务之后,我们定义了一个block,这个block中包含两个任务,两个debug任务分别输出各自的信息,上例的when关键字与block关键字对齐,表示when关键字的条件是针对block的,当when对应的条件成立,则执行block中的两个任务。

    很容易理解对吧,其实,block除了能够与when结合在一起使用,还有一个很有用的功能,就是"错误处理"功能。

    "错误处理"功能就是当某任务出错时,执行指定的其他任务,打个比方,我们想要在A任务执行失败时执行B任务,如果A任务执行成功,则无需执行B任务,实现这个功能,就能够使用block,当然,我们还有一些别的方法,也可以实现类似的功能,比如前文中提到的jinja2的tests,有个一名为failed的test,借助failed也可以实现类似的功能,此处我们先回顾一下failed的用法,然后对比着failed的示例,介绍block的用法,使用failed完成上述错误处理的示例代码如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - shell: 'ls /ooo'
    6.     register: return_value
    7.     ignore_errors: true
    8.   - debug:
    9.       msg: "I cought an error"
    10.     when: return_value is failed
    复制代码
    如上例所示,我在shell任务中执行了'ls /ooo'命令,而test70主机中并不存在/ooo这个路径,所以shell模块执行时一定会出错,我将shell任务执行的返回值注册到了return_value变量中,然后使用"is failed"进行判断,如果条件成立,代表shell任务执行出错,则执行debug任务,输出对应的信息,上述示例就能实现我们刚才所要求的功能,如果用block来实现,该怎样编写playbook呢?来看一个小示例,如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - block:
    6.       - shell: 'ls /ooo'
    7.     rescue:
    8.       - debug:
    9.           msg: 'I caught an error'
    复制代码
    如上例所示,我定义了一个block,这个block中有一个任务,这个任务在目标主机中执行了'ls /ooo'命令,除了block关键字,还有另外一个关键字rescue,rescue关键字与block关键字对齐,rescue的字面意思为"救援",表示当block中的任务执行失败时,会执行rescue中的任务进行补救,当然,在rescue中定义什么任务,是由你决定的,上述示例主要是为了说明,当block中的任务出错时,会执行rescue中的任务,当block中的任务顺利执行时,则不会执行rescue中的任务。

    你可能会问,使用block的方法完成"错误处理"的功能,似乎与使用failed的方法并没有什么不同,除了代码似乎"精简"了一点,block还有其他优势么?其实,使用block的方式还是有一定优势的,当block中有多个任务时,这种优势就比较明显了,我们来看一个小示例,如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - block:
    6.       - shell: 'ls /opt'
    7.       - shell: 'ls /testdir'
    8.       - shell: 'ls /c'
    9.     rescue:
    10.       - debug:
    11.           msg: 'I caught an error'
    复制代码
    如上例所示,block中有三个任务,这三个任务中的任何一个任务出错,都会执行rescue中的任务,所以通常,我们会使用block和rescue结合,完成"错误捕捉,报出异常"的功能,其实,不仅block中可以有多个任务,rescue中也可以定义多个任务,当block中的任何一个任务出错时,会按照顺序执行rescue中的任务。

    你一定已经理解了,我们来扩展一下,上例中只使用到了block与rescue关键字,其实,我们还能够再加入always关键字,加入always关键字以后,无论block中的任务执行成功还是失败,always中的任务都会被执行,示例如下:
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - block:
    6.       - debug:
    7.           msg: 'I execute normally'
    8.       - command: /bin/false
    9.       - debug:
    10.           msg: 'I never execute, due to the above task failing'
    11.     rescue:
    12.       - debug:
    13.           msg: 'I caught an error'
    14.       - command: /bin/false
    15.       - debug:
    16.           msg: 'I also never execute'
    17.     always:
    18.       - debug:
    19.           msg: "This always executes"
    复制代码
    如上例所示,block中有多个任务,rescue中也有多个任务,上例中故意执行"/bin/false"命令,模拟任务出错的情况,当block中的'/bin/false'执行后,其后的debug任务将不会被执行,因为'/bin/false'模拟出错,出错后直接执行rescue中的任务,在执行rescue中的任务时,会先输出 'I caught an error',然后又在rescue中使用'/bin/false'模拟出错的情况,出错后之后的debug任务不会被执行,直接执行always中的任务,always中的任务一定会被执行,无论block中的任务是否出错,快动手测试一下实际的执行效果吧。

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

    帖子永久地址: 

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

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

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