实施任务控制

实施任务控制

一、编写循环和条件任务

1、利用循环迭代任务

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

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

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”:无此用户

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   

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检验以和查看服务是否已更改。

1、条件任务语法

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

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

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

上一篇:with_items 迭代


下一篇:Ansible的常用模块