ansible playbook 中的条件判断与block

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

在ansible中,可以使用"block"关键字将多个任务整合成一个"块",这个"块"将被当做一个整体,我们可以对这个"块"添加判断条件,当条件成立时,则执行这个块中的所有任务,我们来看一个小示例,如下

[root@server4 ~]# vim block1.yml
[root@server4 ~]# cat block1.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - debug:
      msg: "task1 not in block"
  - block: 
      - debug:
          msg: "task2 in block1"
      - debug:
          msg: "task3 in block2" 
    when: 2 > 1

ansible playbook 中的条件判断与block_第1张图片
上例中一共包含三个任务,第一个任务使用debug模块输出了 "task1 not in block"这句话,在第一个任务之后,我们定义了一个block,这个block中包含两个任务,两个debug任务分别输出各自的信息,上例的when关键字与block关键字对齐,表示when关键字的条件是针对block的,当when对应的条件成立,则执行block中的两个任务。

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

"错误处理"功能就是当某任务出错时,执行指定的其他任务,打个比方,我们想要在A任务执行失败时执行B任务,如果A任务执行成功,则无需执行B任务,实现这个功能,就能够使用block,当然,我们还有一些别的方法,也可以实现类似的功能,比如前文中提到的jinja2的tests,有个一名为failed的test,借助failed也可以实现类似的功能,此处我们先回顾一下failed的用法,然后对比着failed的示例,介绍block的用法,使用failed完成上述错误处理的示例代码如下

[root@server4 ~]# vim block3.yml
[root@server4 ~]# cat block3.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - shell: 'ls /ooo'
    register: return_value
    ignore_errors: true
  - debug:
      msg: "i caught an error"
    when: return_value is failed
[root@server4 ~]# ansible-playbook block3.yml 

ansible playbook 中的条件判断与block_第2张图片
如上例所示,我在shell任务中执行了’ls /ooo’命令,而testB主机中并不存在/ooo这个路径,所以shell模块执行时一定会出错,我将shell任务执行的返回值注册到了return_value变量中,然后使用"is failed"进行判断,如果条件成立,代表shell任务执行出错,则执行debug任务,输出对应的信息,上述示例就能实现我们刚才所要求的功能,如果用block来实现,该怎样编写playbook呢?来看一个小示例,如下:

[root@server4 ~]# vim block4.yml
[root@server4 ~]# cat block4.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - block:
      - shell: 'ls /ooo'
    rescue:
      - debug:      
          msg: "i caught an error"

ansible playbook 中的条件判断与block_第3张图片
你可能会问,使用block的方法完成"错误处理"的功能,似乎与使用failed的方法并没有什么不同,除了代码似乎"精简"了一点,block还有其他优势么?其实,使用block的方式还是有一定优势的,当block中有多个任务时,这种优势就比较明显了,我们来看一个小示例,如下:

[root@server4 ~]# vim block5.yml
[root@server4 ~]# cat block5.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - block:
      - shell: 'ls /opt'
      - shell: 'ls /testdir'
      - shell: 'ls /a'
    rescue:
      - debug:      
          msg: "i caught an error"

ansible playbook 中的条件判断与block_第4张图片
如上例所示,block中有三个任务,这三个任务中的任何一个任务出错,都会执行rescue中的任务,所以通常,我们会使用block和rescue结合,完成"错误捕捉,报出异常"的功能,其实,不仅block中可以有多个任务,rescue中也可以定义多个任务,当block中的任何一个任务出错时,会按照顺序执行rescue中的任务:

rescue定义多个任务示例:

[root@server4 ~]# vim block6.yml
[root@server4 ~]# cat block6.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - block:
      - shell: 'ls /opt'
      - shell: 'ls /testdir'
      - shell: 'ls /a'
    rescue:
      - debug:      
          msg: "i caught an error1"
      - debug:
          msg: "i caught an error2"

ansible playbook 中的条件判断与block_第5张图片

always关键字

我们来扩展一下,上例中只使用到了block与rescue关键字,其实,我们还能够再加入always关键字,加入always关键字以后,无论block中的任务执行成功还是失败,always中的任务都会被执行,示例如下:

[root@server4 ~]# vim block3.yml
[root@server4 ~]# cat block3.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - block:
      - debug:
          msg: 'I execute normally'
      - command: /bin/false
      - debug:
          msg: 'I never execute, due to the above task failing'
    rescue:
      - debug:
          msg: 'I caught an error'
      - command: /bin/false
      - debug:
          msg: 'I also never execute'
    always:
      - debug:
          msg: "This always executes"

ansible playbook 中的条件判断与block_第6张图片
ansible playbook 中的条件判断与block_第7张图片
如上例所示,block中有多个任务,rescue中也有多个任务,上例中故意执行"/bin/false"命令,模拟任务出错的情况,当block中的’/bin/false’执行后,其后的debug任务将不会被执行,因为’/bin/false’模拟出错,出错后直接执行rescue中的任务,在执行rescue中的任务时,会先输出 ‘I caught an error’,然后又在rescue中使用’/bin/false’模拟出错的情况,出错后之后的debug任务不会被执行,直接执行always中的任务,always中的任务一定会被执行,无论block中的任务是否出错,快动手测试一下实际的执行效果吧

你可能感兴趣的:(企业实战)