“RHCE8.0讲义:编写循环和条件任务”的版本间的差异

来自CloudWiki
跳转至: 导航搜索
(创建页面,内容为“==利用循环迭代任务== 通过利用循环,管理员无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五…”)
(没有差异)

2021年2月15日 (一) 07:44的版本

利用循环迭代任务

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

Ansible支持使用loop关键字对一组项目迭代任务。您可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。本节介绍迭代项目列表的简单循环。有关更高级的循环方案,请参阅文档。

简单循环

简单循环对一组项目迭代任务。loop关键字添加到任务中,将应对其迭代任务的项目列表取为值。循环变量item保存每个迭代过程中使用的值。

请思考以下代码片段,它使用两次service模块来确保两个网络服务处于运行状态:

- name: Postfix is running
  service:
    name: postfix
    state: started

- name: Dovecot is running
  service:
    name: dovecot
    state: started

这两个任务可以重新编写为使用一个简单循环,从而只需一个任务来确保两个服务都在运行:

- name: Postfix and Dovecot are running service: name: "{{ item })" state: started loop: - postfix - dovecot

可以通过一个变量提供丄oop所使用的列表。在以下示例中'变量mail_services含有需要处于 运行状态的服务的列表。

vars:
   mail_services:
     - postfix
     - dovecot

tasks:
  - name: Postfix and Dovecot are running
    service:
      name: "{( item })"
      state: started
      loop: ”{{ mail_services }}*'

循环散列或字典列表

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

- name: Users exist and are in the correct groups
  user:
    name: ”{{ item.name }}"
    state: present
    groups: "(( item.groups })"
  loop:
    - name: jane
      groups: wheel
    - name: joe
      groups: root

上一任务的结果是用户jane存在且为组wheel的成员,并且用户joe存在且为组root的成员。


较早样式的循环关键字

在Ansible 2.5之前,大多数playbook使用不同的循环语法。提供了多个循环关键字,前缀为 with_ ,后跟Ansible查找插件(一项高级功能,本课程中未加以详细介绍)的名称。这种循环语 法在现有playbook中很常见,但在将来的某个时候可能会被弃用。

下表列出了几个示例:

较早样式的Ansible循环

循环关键字	描述
with_items	行为与简单列表的loop关键字相同,例如字符串列表或散列/字典 列表。但与loop不同的是,如果为with_items提供了列表的列 表,它们将被扁平化为单级列表。循环变量item保存每次迭代过 程中使用的列表项。
with_file	此关键字需要控制节点文件名列表。循环变量item在每次迭代过 程中保存文件列表中相应文件的内容。
with_sequence	此关键字不需要列表,而是需要参数来根据数字序列生成值列表。 循环变量item在每次迭代过程中保存生成的序列中的一个生成项 的值。


playbook中的with_items的示例如下所示:

vars: data: - user0 - user1 - user2 tasks: - name: "with_items" debug: msg: "{{ item }}" with_items: "(( data }}"

重要

从Ansible 2.5开始,建议使用loop关键字编写循环。

但是,您仍然应该了解旧语法,尤其是with_items,因为它广泛用于现有 playbooko您可能会遇到继续使用with_*关键字进行循环的playbook和角色。

使用旧语法的任何任务都可以转换为结合使用loop和Ansible过滤器。您不需要知道如何使用 Ansible过滤器来执行此操作。有关如何将旧循环转换为新语法,以及如何循环不是简单列表的 项的示例,Ansible 用户指南第从 with_X迁移至循环[https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#migrating-from-with-x-to-loop]节中的 Ansible 文档提供了 良好 的参善。

您可能会遇到包含with_*关键字的旧playbook中的任务。

高级循环技术不在本课程的讨论范围内。本课程中的所有迭代任务都可以使用withjtems或 loop关键字实施。

将Register变量与Loop —起使用

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

[student@workstation loopdemo]$ cat loop_register.yml

- name: Loop Register Test

 gather_facts: no
 hosts: localhost
 tasks:
  - name: Looping Echo Task
    shell: "echo This is my item: {{ item })"
    loop:
      - one
      - two
    register: echo_results (1)
  - name: Show echo_results variable
    debug:
      var: echo_results (2)

(1) echo_results变量已注册。

(2)echo_results变量的内容显示在屏幕上。

运行上面的playbook会产生以下输出:

[student@workstation loopdemo]$ ansible-playbook loop_register.yml play

[Loop Register Test] ****************************************
TASK [Looping Echo Task] ************************** ... output omitted
TASK [Show echo_results variable] ***************** ok: [localhost] => {
"echo_results": {。
"changed": true,
"msg": "All items completed",
"results" : [O
"_ansible_ignore_errors": null,
... output omitted
"changed": true,
"cmd": "echo This is my item: one",
"delta": "0:00:00.011865",
"end": "2018-11-01 16:32:56.080433", "failed": false,
...output omitted
"item": "one",
"re": 0,
"start": "2018-11-01 16:32:56.068568", "stderr":
"stderr_lines":
"stdout": "This
"stdout_lines":
"This is my
]
},
{O
"_ansible_ignore_errors": null,
... output omitted
"changed": true,
"cmd": "echo This is my item: two", "delta": "0:00:00.011142"z
"end": "2018-11-01 16:32:56.828196", "failed": false,
... output omitted
"item": "two",
"rc": 0,
"start": "2018-11-01 16:32:56.817054", "stderr" : ,,n,
"stderr_lines":
"stdout": "This
"stdout_lines":
"This is my
]
}
[],
is my item: one",
item: one
口,
is my item: two",
item: two"
]❺
}
}
... output omitted

{字符表示echo_results变量的开头由键值对组成。

results譴包含上一个任务的结果。[字符表示列表的开头。

第一项的任务元数据的开头(由item键表示)。echo命令的输出可在stdout键中找至U。 第二项的任务结果元数据的幵头。

]字符表示results列表的结尾。

在上面,results键包含一个列表。在下面,修改了 playbook,使第二个任务迭代此列表:

[student@workstation loopdemo]$ cat new_loop_register.yml

- name: Loop Register Test
  gather_facts: no
  hosts: localhost
  tasks:
   - name: Looping Echo Task
     shell: "echo This is my item: {{ item })"
     loop:
       - one
       - two
     register: echo_results 
   - name: Show stdout from the previous task.
     debug:
       msg: "STDOUT from previous task: {( item.stdout })" 
     loop: "{{ echo_results['results'] }}"

执行上述playbook后,输出为:

PLAY [Loop Register Test] *****************
TASK [Looping Echo Task] ***************************************************** …output omitted
TASK [Show stdout from the previous task.] ******************** ok:
[localhost]=> "msg": "STDOUT
(item={...output omitted...=> { from previous task: This is my item: one
}
ok:
[localhost]=> "msg": "STDOUT
(item={...output omitted...)) => { from previous task: This is my item: two"
}
... output omitted