实施任务控制

一、编写循环和条件任务

1、利用循环迭代任务

通过利用循环,我们无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。

​ Ansible支持使用loop关键字对一组项目迭代任务。可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。

1.1简单循环

[root@ansible project]# cat playbook/test.yml 
---
- hosts: httpd
  gather_facts: no
  tasks:
    - name: create user {{ item }}
      user:
        name: "{{ item }}"
        state: present
      loop:
        - tom1
        - tom2
        - tom3

这样就可以让他们进行逐一的创建用户,执行一下这个playbook看看效果:

[root@ansible project]# ansible-playbook  playbook/test.yml 
PLAY [httpd] ******************************************************************************************************************

TASK [create user {{ item }}] **************************************************************************************************************************************
changed: [192.168.129.135] => (item=tom1)
changed: [192.168.129.135] => (item=tom2)
changed: [192.168.129.135] => (item=tom3)

PLAY RECAP *****************************************************************************************
192.168.129.135            : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

我们也可以通过一个变量提供loop所使用的列表。在以下示例中,变量users含有需要创建的用户:

[root@ansible project]# cat playbook/test.yml 
---
- hosts: httpd
  gather_facts: no
  vars:
    users:
      - tom1
      - tom2
      - tom3
  tasks:
    - name: create user {{ item }}
      user:
        name: "{{ item }}"
        state: present
      loop:
        "{{ user }}"

效果:

[root@httpd ~]# id tom1
uid=1002(tom1) gid=1002(tom1)=1002(tom1)
[root@httpd ~]# id tom2
uid=1003(tom2) gid=1003(tom2)=1003(tom2)
[root@httpd ~]# id tom3
uid=1004(tom3) gid=1004(tom3)=1004(tom3)

删除刚创建的用户

[root@ansible project]# cat playbook/vars/yonghu.yml 
user:
  - tom1
  - tom2
  - tom3

[root@ansible project]# cat playbook/test.yml 
---
- hosts: httpd
  gather_facts: no
  vars_files:
    - vars/yonghu.yml
  tasks:
    - name: create user {{ item }}
      user:
        name: "{{ item }}"
        state: absent
      loop:
        "{{ user }}"

执行看效果

[root@ansible project]# ansible-playbook  playbook/test.yml 
PLAY [httpd] ************************************************************************************************************

TASK [create user {{ item }}] *******************************************************************************************
changed: [192.168.129.135] => (item=tom1)
changed: [192.168.129.135] => (item=tom2)
changed: [192.168.129.135] => (item=tom3)

PLAY RECAP **************************************************************************************************************
192.168.129.135            : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

查看用户是否删除

[root@httpd ~]# id tom3
id: “tom3”:无此用户
[root@httpd ~]# id tom2
id: “tom2”:无此用户
[root@httpd ~]# id tom1
id: “tom1”:无此用户

1.2 循环散列或字典列表

loop列表不需要是简单值列表。在以下示例中,列表中的每个项实际上是散列或字典。示例中的每个散列或字典具有两个键,即name和groups,当前item循环变量中每个键的值可以分别通过item.nameitem.groups变量来检索。

[root@ansible project]# cat playbook/vars/yonghu.yml 
user:
  - tom1
  - tom2
  - tom3

[root@ansible project]# cat playbook/test.yml 
---
- hosts: httpd
  gather_facts: no
  vars_files:
    - vars/yonghu.yml
  tasks:
    - name: create user {{item.name}}
      user:
        name: "{{ item.name }}"
        uid: "{{ item.uid }}"
        state: present
      loop:
        - name: tom1
          uid: 2000
        - name: tom2
          uid: 2001
        - name: tom3
          uid: 2002

运行查看效果

[root@ansible project]# ansible-playbook  playbook/test.yml 

PLAY [httpd] ************************************************************************************************************

TASK [create user {{item.name}}] ****************************************************************************************
changed: [192.168.129.135] => (item={'name': 'tom1', 'uid': 2000})
changed: [192.168.129.135] => (item={'name': 'tom2', 'uid': 2001})
changed: [192.168.129.135] => (item={'name': 'tom3', 'uid': 2002})

PLAY RECAP **************************************************************************************************************
192.168.129.135            : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
[root@httpd ~]# id tom1
uid=2000(tom1) gid=2000(tom1)=2000(tom1)
[root@httpd ~]# id tom2
uid=2001(tom2) gid=2001(tom2)=2001(tom2)
[root@httpd ~]# id tom3
uid=2002(tom3) gid=2002(tom3)=2002(tom3)

我们也可以通过配置文件

[root@ansible project]# cat playbook/vars/yonghu.yml 
user:
  - name: tom1
    uid: 2000
  - name: tom2
    uid: 2001
  - name: tom3
    uid: 2002

[root@ansible project]# cat playbook/test.yml 
---
- hosts: httpd
  gather_facts: no
  vars_files:
    - vars/yonghu.yml
  tasks:
    - name: create user {{item.name}}
      user:
        name: "{{ item.name }}"
        uid: "{{ item.uid }}"
        state: absent
      loop: "{{ user }}"

运行查看效果

[root@ansible project]# ansible-playbook  playbook/test.yml 

PLAY [httpd] ************************************************************************************************************

TASK [create user {{item.name}}] ****************************************************************************************
changed: [192.168.129.135] => (item={'name': 'tom1', 'uid': 2000})
changed: [192.168.129.135] => (item={'name': 'tom2', 'uid': 2001})
changed: [192.168.129.135] => (item={'name': 'tom3', 'uid': 2002})

PLAY RECAP **************************************************************************************************************
192.168.129.135            : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

1.3 将Register变量与Loop一起使用

register关键字也可以捕获循环任务的输出。以下代码片段显示了循环任务中register变量的结构:

首先编辑一个变量文件

[root@ansible project]# cat playbook/vars/yonghu.yml 
user:
  - name: lisi
    uid: 2000
  - name: liubai
    uid: 2002

其次编写循环语句

 [root@ansible project]# cat playbook/uu.yml 
---
- hosts: httpd
  tasks:
    - name: Looping Echo Task
      command: "echo hello {{ item }},nice to meet you."
      loop:
        - lisi
        - liubai
      register: echo_results    # 注册echo_results变量

    - name: Show echo_results variable 
      debug:
        var: echo_results       # echo_results变量的内容显示在屏幕上
[root@httpd ~]# id lisi
uid=2000(lisi) gid=2000(lisi)=2000(lisi)
[root@httpd ~]# id liubai 
uid=2002(liubai) gid=2002(liubai)=2002(liubai)

之后运行

[root@ansible project]# ansible-playbook playbook/uu.yml 

PLAY [httpd] ************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************
ok: [192.168.129.135]

TASK [Looping Echo Task] ************************************************************************************************
changed: [192.168.129.135] => (item=lisi)
changed: [192.168.129.135] => (item=liubai)

TASK [Show echo_results variable] ***************************************************************************************
ok: [192.168.129.135] => {
    "echo_results": {
        "changed": true,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": [
                    "echo",
                    "hello",
                    "lisi,nice",
                    "to",
                    "meet",
                    "you."
                ],
                "delta": "0:00:00.003232",
                "end": "2021-07-25 13:35:41.991754",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo hello lisi,nice to meet you.",
                        "_uses_shell": false,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "lisi",
                "rc": 0,
                "start": "2021-07-25 13:35:41.988522",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "hello lisi,nice to meet you.",
                "stdout_lines": [
                    "hello lisi,nice to meet you."
                ]
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": [
                    "echo",
                    "hello",
                    "liubai,nice",
                    "to",
                    "meet",
                    "you."
                ],
                "delta": "0:00:00.002077",
                "end": "2021-07-25 13:35:42.359590",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo hello liubai,nice to meet you.",
                        "_uses_shell": false,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "liubai",
                "rc": 0,
                "start": "2021-07-25 13:35:42.357513",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "hello liubai,nice to meet you.",
                "stdout_lines": [
                    "hello liubai,nice to meet you."
                ]
            }
        ]
    }
}

PLAY RECAP **************************************************************************************************************
192.168.129.135            : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

2、有条件第运行任务

Ansible可使用conditionals在符合特定条件时执行任务或play。例如,可以利用一个条件在Ansible安装或配置服务前确定受管主机上的可用内存。

​ 我们可以利用条件来区分不同的受管主机,并根据它们所符合的条件来分配功能角色。Playbook变量、注册的变量和Ansible事实都可通过条件来进行测试。可以使用比较字符串、数字数据和布尔值的运算符。

以下场景说明了在Ansible中使用条件的情况:

  • 可以在变量中定义硬限制(如min_memory)并将它与受管主机上的可用内存进行比较。
  • Ansible可以捕获并评估命令的输出,以确定某一任务在执行进一步操作前是否已经完成。例如,如果某一程序失败,则将路过批处理。
  • 可以利用Ansible事实来确定受管主机网络配置,并决定要发送的模板文件(如,网络绑定或中继)。
  • 可以评估CPU的数量,来确定如何正确调节某一Web服务器。
  • 将注册的变量与预定义的变量进行比较,以确定服务是否已更改。例如,测试服务配置文件的MD5检验以和查看服务是否已更改。

2.1 条件任务语法

​ when语句用于有条件地运行任务。它取要测试的条件为值。如果条件满足,则运行任务。如果条件不满足,则跳过任务。

可以测试的一个最简单条件是某一布尔变量是True还是False。以下示例中的when语句导致任务仅在run_my_taskTrue时运行:

[root@ansible project]# cat playbook/uu.yml 
---
- hosts: httpd
  gather_facts: no
  vars:
    run_my_task: true
  tasks:
    - name: httpd package is installed
      yum:
        name: httpd
      when: run_my_task

[root@ansible project]# ansible-playbook playbook/uu.yml 
PLAY [httpd] ******************************************************************************************

TASK [httpd package is installed] *********************************************************************
changed: [192.168.129.135]

PLAY RECAP ********************************************************************************************
192.168.129.135            : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0  

以下示例测试my_service变量是否具有值。若有值,则将my_service的值用作要安装的软件包的名称。如果未定义my_service变量,则跳过任务且不显示错误。

[root@ansible project]# cat playbook/uu.yml 
---
- hosts: httpd
  gather_facts: no
  vars:
    my_service: httpd
  tasks:
    - name: "{{ my_service }} package is installed"
      yum:
        name: "{{ my_service }}"
        state: latest
      when: my_service is defined

示例条件

操作示例
等于(值为字符串)ansible_machine == “x86_64”
等于(值为数字)max_memory == 512
小于min_memory < 128
大于min_memory > 256
小于等于min_memory <= 256
大于等于min_memory >= 512
不等于min_memory != 512
变量存在min_memory is defined
变量不存在min_memory is not defined
布尔变量是True。1、True或yes的求值为Truememory_available
布尔变量是False。0、False或no的求值为Falsenot memory_available
第一个变量的值存在,作为第二个变量的列表中的值ansible_distribution in supported_distros

在示例中,ansible_distribution变量是在Gathering Facts任务期间确定的事实,用于标识托管主机的操作系统分支。变量supported_distros由playbook创建,包含该playbook支持的操作系统分发列表。如果ansible_distribution的值在supported_distros列表中,则条件通过且任务运行。

[root@ansible project]# cat playbook/uu.yml 
---
- name: Demonstrale the "in" keyword
  hosts: httpd
  gather_facts: yes
  vars:
    supported_distros:
      - RedHat
      - Fedora
  tasks:
    - name: Install httpd using yum, where supported
      yum:
        name: httpd
        state: present
      when: ansible_distribution in supported_distros

2.2 测试多个条件

一个when语句可用于评估多个条件。使用and和or关键字组合条件,并使用括号分组条件。

如果任一条件为真时满足条件语句,则应当使用or语句。例如,如果计算机上运行的是红帽企业linux或Fedora,则下述条件得到满足:

[root@192 project]# cat playbook/test.yml 
---
- name: seshi
  hosts: web
  vars:
    my_service: httpd
  tasks:
    - name: test
      yum:
        name: "{{ my_service }}"
        state: latest
      when: ansible_distribution == "Redhat" or ansible_distribution == "Fedora"

[root@192 project]# ansible-playbook playbook/test.yml 

PLAY [seshi] ******************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [192.168.129.137]

TASK [test] *******************************************************************************************
skipping: [192.168.129.137]

PLAY RECAP ********************************************************************************************
192.168.129.137            : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

使用and运算时,两个条件都必须为真,才能满足整个条件语句。例如,如果远程主机是红帽企业Linux7.5主机,并且安装的内核是指定版本,则将满足以下条件:

[root@192 project]# cat playbook/test.yml
---
- name: seshi
  hosts: web
  vars:
    my_service: httpd
  tasks:
    - name: test
      yum:
        name: "{{ my_service }}"
        state: latest
      when: ansible_distribution_version == "8.2" and ansible_architecture == "x86_64"
      
[root@192 project]# ansible-playbook playbook/test.yml 

PLAY [seshi] ******************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [192.168.129.137]

TASK [test] *******************************************************************************************
changed: [192.168.129.137]

PLAY RECAP ********************************************************************************************
192.168.129.137            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

也可以这样写:

when:
  - ansible_distribution_version == "8.2"
  - ansible_architecture == "x86_64"

通过使用括号分组条件,可以表达更复杂的条件语句。例如,如果计算机上运行的是红帽企业Linux7或Fedora28,则下述条件语句得到满足。此示例使用大于字符,这样长条件就可以在playbook中分成多行,以便于阅读。

when: >
  ( ansible_distribution == "Redhat" and
    ansible_distribution_major_version == "8" )
  or
  ( ansible_distribution == "Fedora" and
    ansible_distribution_major_version == "28" )

3、组合循环和有条件任务

循环和条件可以组合使用。

[root@192 project]# cat playbook/test.yml
---
- name: install mariadb-server if enough space on root
  hosts: web
  tasks:

    - name: test
      yum:
        name: mariadb-server
        state: latest
      loop: "{{ ansible_mounts }}"
      when: item.mount == "/" and item.size_available > 300000000

对某个任务结合使用when和loop时,将对每个项检查when语句。

下面是组合使用条件和注册变量的另一个示例

---
- name: Restart HTTPD if Postfix is Running
  hosts: 172.16.103.129
  tasks:
    - name: Get Postfix server status
      command: /usr/bin/systemctl is-active postfix     # Postfix是否在运行?
      ignore_errors: yes    # 如果它不在运行并且命令失败,则不停止处理。
      register: result      # 将模块的结果信息保存在名为result的变量中
      
    - name: Restart Apache HTTPD based on Postfix status
      service:
        name: httpd
        state: restarted
      when: result.rc == 0      # 评估Postfix任务的输出。如果systemctl命令的退出代码为0,\
                                # 则Postfix激活并且此任务重启httpd服务

二、实施处理程序

1、ansible处理程序

使用notify语句来调用一个任务的触发,只有当任务的结果为change时,才会调用任务

​ 在下列代码片段中,只有配置文件更新并且通知了该任务,restart apache处理程序才会重启Apache服务:

---
- name: test
  hosts: all
  tasks:
    - name: change config		# 通知处理程序的任务
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        regexp: "^Listen 80"
        line: "Listen 8080"
      notify:		# notify语句指出该任务需要触发一个处理程序
        - restart apache		# 要运行的处理程序的名称
          
  handlers:		# handlers关键字表示处理程序任务列表的开头
    - name: restart apache		# 被任务调用的处理程序的名称(被任务调用的处理程序与运行的处理程序名称必须一样)
      service:		# 用于该处理程序的模块
        name: httpd
        state: restarted

在上面的例子中,restart apache处理程序只有在template任务通知已发生更改时才会触发。一个任务可以在其notify部分中调用多个处理程序。Ansible将notify语句视为数组,并且迭代处理程序名称:

---
- name: test
  hosts: all
  tasks:
    - name: change config
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        regexp: "^Listen 80"
        line: "Listen 8080"
      notify:
        - restart apache
        - restart mysql
          
  handlers:
    - name: restart apache
      service:
        name: httpd
        state: restarted
        
    - name: restart mysql
      service:
        name: mariadb
        state: restarted

2、调用使用处理程序的好处

使用处理程序时需要牢记几个重要事项:

  • 处理程序始终按照play的handlers部分指定的顺序运行。它们不按在任务中由notify语句列出的顺序运行,或按任务通知它们的顺序运行。
  • 处理程序通常在相关play中的所有其他任务完成后运行。playbook的tasks部分中某一任务调用的处理程序,将等到tasks下的所有任务都已处理后才会运行。
  • 处理程序名称存在于各play命名空间中。如果两个处理程序被错误地给予相同的名称,则仅会运行一个。
  • 即使有多个任务通知处理程序,该处理程序依然仅运行一次。如果没有任务通知处理程序,它就不会运行。
  • 如果包含notify语句的任务没有报告changed结果(例如,软件包已安装并且任务报告ok),则处理程序不会获得通知。处理程序将被跳过,直到有其他任务通知它。只有相关任务报告了changed状态,Ansible才会通知处理程序。

处理程序用于在任务对受管主机进行更改时执行额外操作。它们不应用作正常任务的替代。

三、处理任务失败

1、忽略任务失败

默认情况下,任务失败时play会中止。不过,可以通过忽略失败的任务来覆盖此行为。可以在任务中使用ignore_errors关键字来实现此目的。

下列代码片段演示了如何在任务中使用ignore_errors,以便在任务失败时也继续在主机上执行playbook。例如,如果notapkg软件包不存在,则yum模块将失败,但若将ignore_errors设为yes,则执行将继续。

[root@192 project]# cat playbook/test.yml 
---
- hosts: web
  name: test
  tasks:
    - name: nopackage
      yum:
        name: nopackage
        state: present
      ignore_errors: yes
      
[root@192 project]# ansible-playbook playbook/test.yml 
PLAY [test] *******************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [192.168.129.137]

TASK [nopackage] **************************************************************************************
fatal: [192.168.129.137]: FAILED! => {"changed": false, "failures": ["No package nopackage available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
...ignoring

PLAY RECAP ********************************************************************************************
192.168.129.137            : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   

2、任务失败后强制执行处理程序

通常而言,如果任务失败并且play在该主机上中止,则收到play中早前任务通知的处理程序将不会运行。如果在play中设置force_handlers: yes关键字,则即使play因为后续任务失败而中止也会调用被通知的处理程序。

下列代码片段演示了如何在play中使用force_handlers关键字,以便在任务失败时也强制执行相应的处理程序:

[root@192 project]# cat playbook/test.yml 
---
- hosts: web
  force_handlers: yes
  name: test
  tasks:
    - name: a task which always notifies its handler
      command: /bin/true
      notify: restart the database

    - name: a task which fails because the package doesn't exist
      yum: 
        name: notapkg
        state: latest

  handlers:
    - name: restart the database
      service:
        name: mariadb
        state: restarted

[root@192 project]# ansible-playbook playbook/test.yml 

PLAY [test] *******************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [192.168.129.137]

TASK [a task which always notifies its handler] *******************************************************
changed: [192.168.129.137]

TASK [a task which fails because the package doesn't exist] *******************************************
fatal: [192.168.129.137]: FAILED! => {"changed": false, "failures": ["No package notapkg available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}

RUNNING HANDLER [restart the database] **********************尽管前面有任务失败,但还是执行了handlers******************************************
changed: [192.168.129.137]

PLAY RECAP ********************************************************************************************
192.168.129.137            : ok=3    changed=2    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0 

请记住,处理程序会在任务报告changed结果时获得通知,而在任务报告okfailed结果时不会获得通知

3、指定任务失败条件

可以在任务中使用failed_when关键字来指定表示任务已失败的条件。这通常与命令模块搭配使用,这些模块可能成功执行了某一命令,但命令的输出可能指示了失败。

例如,可以运行输出错误消息的脚本,并使用该消息定义任务的失败状态。下列代码片段演示了如何在任务中使用failed_when关键字:

[root@192 project]# cat playbook/test.yml 
---
- hosts: web
  name: test
  tasks:
  - name: test
    command: echo "hello jjyy"
    register: result
    failed_when: "'jjyy' in result['stdout']"

fail模块也可用于强制任务失败

[root@192 project]# cat playbook/test.yml 
---
- hosts: web
  name: test
  tasks:
  - name: test
    command: echo "hello jjyy"
    register: result

  - name: Already exists
    fail:
      msg: "I'm afraid you're a fool!"
    when: "'jjyy' in result['stdout']"

[root@192 project]# ansible-playbook playbook/test.yml 

PLAY [test] *******************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [192.168.129.137]

TASK [test] *******************************************************************************************
changed: [192.168.129.137]

TASK [Already exists] *********************************************************************************
fatal: [192.168.129.137]: FAILED! => {"changed": false, "msg": "I'm afraid you're a fool!"}

PLAY RECAP ********************************************************************************************
192.168.129.137            : ok=2    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

4、指定何时任务报告 “Changed” 结果

​ 当任务对托管主机进行了更改时,会报告 changed 状态并通知处理程序。如果任务不需要进行更改,则会报告ok并且不通知处理程序。
false:不报告changed,只报告ok
true: 一定报告changed

​ changed_when关键字可用于控制任务在何时报告它已进行了更改。下面这个例子中,我们修改了用户的uid,使用changed_when: false以后,它的结果变成了ok

- name: get Kerberos credentials as "admin"
  shell: echo "{{ krb_admin_pass }}" | kinit -f admin
  changed_when: false
[root@192 project]# cat playbook/test.yml 
---
- hosts: web
  name: test
  tasks:
    - name: test
      user:
        name: hhh
        uid: 2001 
      changed_when: true

[root@192 project]# ansible-playbook playbook/test.yml 

PLAY [test] *******************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [192.168.129.137]

TASK [test] *******************************************************************************************
ok: [192.168.129.137]

PLAY RECAP ********************************************************************************************
192.168.129.137            : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

5、Ansible块和错误处理

在playbook中,块是对任务进行逻辑分组的子句,可用于控制任务的执行方式。例如,任务块可以含有when关键字,以将某一条件应用到多个任务:

- name: block example
  hosts: web
  tasks:
    - name: installing and configuring Yum versionlock plugin
      block:
      - name: package needed by yum
        yum:
          name: yum-plugin-versionlock
          state: present
      - name: lock version of tadata
        lineinfile:
          dest: /etc/yum/pluginconf.d/versionlock.list
          line: tzdata-2020j-1
          state: present
      when: ansible_distribution == "Redhat"

通过块,也可结合rescue和always语句来处理错误。如果块中的任何任务失败,则执行其rescue块中的任务来进行恢复。在block子句中的任务以及rescue子句中的任务(如果出现故障)运行之后,always子句中的任务运行。总结:

  • block:定义要运行的主要任务
  • rescue:定义要在block子句中定义的任务失败时运行的任务
  • always:定义始终都独立运行的任务,不论block和rescue子句中定义的任务是成功还是失败

以下示例演示了如何在playbook中实施块。即使block子句中定义的任务失败,rescue和always子句中定义的任务也会执行。

[root@192 project]# cat playbook/test.yml 
---
- hosts: web
  name: test
  tasks:
    - name: test
      block:		//如果我任务执行成功了 ,那么rescue任务就不执行,如果执行失败,就执行rescure里面的
        - name: block
          shell: echo 'block'

      rescue:
        - name: rescue
          shell: echo 'rescue'

      always:		//不管上面成功不成功,alway是一定会执行的
        - name: always
          shell: echo 'always'

[root@192 project]# ansible-playbook playbook/test.yml 

PLAY [test] *******************************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [192.168.129.137]

TASK [block] ******************************************************************************************
changed: [192.168.129.137]

TASK [always] *****************************************************************************************
changed: [192.168.129.137]

PLAY RECAP ********************************************************************************************
192.168.129.137            : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

block中的when条件也会应用到其rescue和always子句(若存在)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值