金鱼哥说Ansible:第五章 实施任务控制---编写循环任务
快捷玩Ansible循环任务
IT民工金鱼哥希望能以通俗易懂、诙谐幽默的方式把Ansible体系文章呈现给大家,让枯燥的知识点、让繁重的学习变的有趣一些。
某金鱼小弟闯荡江湖一段时日,于某日发现其所学Ansible的招式不够应对二、三流门派的鱼虾蟹(突然一个声音:这么水吗?),故而闭关修炼。沉思如何做掉这些曾欺负过他的人,忽然天上一闪,一招“循环”招式植入脑海,于是乎马上演练:
1. 招式简介—利用循环迭代任务
在Ansible编写剧本的时候,我们往往遇到许多重复性的操作,比如安装各种软件包,在某个目录操作各种文件等等。通过利用循环,我们无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。
Ansible支持使用loop关键字对一组项目迭代任务。可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。
2. 基础演练—编写简单循环
循环可对一组项目进行迭代任务。使用loop关键字添加到任务中,将应对其迭代任务的项目列表取为值。循环变量item保存每个迭代过程中使用的值。可以理解为loop和item就是一配对。
举个例子:
不用循环的写法:
---
- hosts: localhost
tasks:
- name: mkdir /home/student/abc
shell: mkdir /home/student/abc
- name: mkdir /home/student/cde
shell: mkdir /home/student/cde
使用简单的循环:
# cat test.yml
---
- hosts: localhost
tasks:
- name: mkdir /home/student/ file
shell: "mkdir /home/student/{{ item }}"
loop:
- abc
- cde
明显使用一次shell模块,而不用使用二次就可以达到最终的需求。(突然感觉气血通畅,爽!)
还有另一种写法:
(这种偏门点的招式,还是看看就好)
---
- hosts: localhost
vars:
dir_name:
- abc
- cde
tasks:
- name: mkdir /home/student/ file
shell: "mkdir /home/student/{{ item }}"
loop: "{{ dir_name }}"
3. 招式外放—循环散列或字典列表
loop列表可不以简单的值作为调用,而是使用散列或字典,这较为复杂一点的写法。
在以下示例中,列表中的每个项实际上是散列或字典。示例中的每个散列或字典具有两个键,即name和groups,当前item循环变量中每个键的值可以分别通过item.name和item.groups变量来检索。
---
- hosts: localhost
tasks:
- name: user loop test
user:
name: "{{ item.name }}"
state: present
group: "{{ item.group }}"
loop:
- name: chap
group: chap
- name: rebel
group: rebel
(还记得上文所说的loop和item配对吗?item.name
其实就是 loop.name
,人家是比翼双飞,水影鸳鸾 >.<)
较早样式的循环关键字
在Ansible2.5之前,大多数playbook使用不同的循环语法。提供了多个循环关键字,前缀为with_,后面跟Ansible查找插件的名称。这种循环语法在现有playbook中很常见,但在将来的某个时候可能会被弃用。
(看来招式还是需要定期更新才行,不过在人家还没有过时前,还是得先见招拆招。)
较早样式的Ansible循环
循环关键字 | 描述 |
---|---|
with_items | 行为与简单列表的loop关键字相同,例如字符串列表或散列/字典列表。但与loop不同的是,如果为with_items提供了列表的列表,它们将被扁平化为单级列表。循环变量item保存每次迭代过程中使用的列表项。 |
with_file | 此关键字需要控制节点文件名列表。循环变量item在每次迭代过程中保存文件列表中相应文件的内容。 |
with_sequence | 此关键字不需要列表,而是需要参数来根据数字序列生成值列表。循环变量item在每次迭代过程中保存生成的序列中的一个生成项的值。 |
with_****items循环playbook演示:
---
- hosts: localhost
vars:
data:
- abc
- cde
- efg
tasks:
- name: with_item test
debug:
msg: "{{ item }}"
with_items: "{{ data }}"
(看来还是现在的爽,一个loop搞掂。)
4. 一剑定江山—将Register变量与Loop一起使用
register关键字也可以用来捕获循环任务的输出。以下代码片段显示了循环任务中register变量的结构:
register和loop配合使用
[student@servera example]$ cat loop-register.yml
---
- hosts: localhost
tasks:
- name: register and loop
shell: "echo test {{ item }}"
loop:
- abc
- cde
register: results
- name: print result
debug:
var: results
[student@servera example]$ ansible-playbook loop-register.yml
PLAY [loop-register] *******************************************************************
TASK [Gathering Facts] *****************************************************************
ok: [localhost]
TASK [register and loop] ***************************************************************
changed: [localhost] => (item=abc)
changed: [localhost] => (item=def)
TASK [print result] ********************************************************************
ok: [localhost] => {
"results": {
"changed": true,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": true,
"cmd": "echo test abc",
"delta": "0:00:00.007471",
"end": "2021-12-09 23:47:00.084344",
"failed": false,
"invocation": {
"module_args": {
"_raw_params": "echo test abc",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "abc",
"rc": 0,
"start": "2021-12-09 23:47:00.076873",
"stderr": "",
"stderr_lines": [],
"stdout": "test abc",
"stdout_lines": [
"test abc"
]
},
{
"ansible_loop_var": "item",
"changed": true,
"cmd": "echo test def",
"delta": "0:00:00.007672",
"end": "2021-12-09 23:47:00.259170",
"failed": false,
"invocation": {
"module_args": {
"_raw_params": "echo test def",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "def",
"rc": 0,
"start": "2021-12-09 23:47:00.251498",
"stderr": "",
"stderr_lines": [],
"stdout": "test def",
"stdout_lines": [
"test def"
]
}
]
}
}
PLAY RECAP *****************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
更进一步的运用:
[student@servera example]$ cat loop-register.yml
---
- name: loop-register
hosts: localhost
tasks:
- name: register and loop
shell: "echo test {{ item }}"
loop:
- abc
- cde
register: results
- name: print results
debug:
msg: "Send out the message: {{ item.stdout }}"
loop: "{{ results['results'] }}"
# 此为运用散列或字典列表的形式,将results这注册变量所输出项中取results项中的值。
# loop: "{{ results.results }}"
# 还记得这个一样的写法吗~~不记得可参考https://bbs.huaweicloud.com/blogs/345403 章节中,新旧语法对比。
[student@servera example]$ ansible-playbook loop-register.yml
PLAY [loop-register] *******************************************************************
TASK [Gathering Facts] *****************************************************************
ok: [localhost]
TASK [register and loop] ***************************************************************
changed: [localhost] => (item=abc)
changed: [localhost] => (item=def)
TASK [print results] *******************************************************************
ok: [localhost] => (item={u'stderr_lines': [], u'ansible_loop_var': u'item', u'end': u'2021-12-09 23:41:27.978177', u'stderr': u'', u'stdout': u'test abc', u'changed': True, u'failed': False, u'delta': u'0:00:00.007256', u'cmd': u'echo test abc', u'item': u'abc', u'rc': 0, u'invocation': {u'module_args': {u'warn': True, u'executable': None, u'_uses_shell': True, u'strip_empty_ends': True, u'_raw_params': u'echo test abc', u'removes': None, u'argv': None, u'creates': None, u'chdir': None, u'stdin_add_newline': True, u'stdin': None}}, u'stdout_lines': [u'test abc'], u'start': u'2021-12-09 23:41:27.970921'}) => {
"msg": "Send out the message: test abc"
}
ok: [localhost] => (item={u'stderr_lines': [], u'ansible_loop_var': u'item', u'end': u'2021-12-09 23:41:28.148281', u'stderr': u'', u'stdout': u'test def', u'changed': True, u'failed': False, u'delta': u'0:00:00.007047', u'cmd': u'echo test def', u'item': u'def', u'rc': 0, u'invocation': {u'module_args': {u'warn': True, u'executable': None, u'_uses_shell': True, u'strip_empty_ends': True, u'_raw_params': u'echo test def', u'removes': None, u'argv': None, u'creates': None, u'chdir': None, u'stdin_add_newline': True, u'stdin': None}}, u'stdout_lines': [u'test def'], u'start': u'2021-12-09 23:41:28.141234'}) => {
"msg": "Send out the message: test def"
}
PLAY RECAP *****************************************************************************
localhost: ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
💡总结
- 理解Ansible循环任务的使用场景。
- 运用loop与item编写循环任务。
- 理解循环任务与注册变量的搭配。
以上就是【金鱼哥】对 第五章 实施任务控制----编写循环任务 的简述和讲解。希望能对看到此文章的小伙伴有所帮助。
如果这篇【文章】有帮助到你,希望可以给【金鱼哥】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【运维技术】感兴趣,也欢迎关注❤️❤️❤️ 【金鱼哥】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!
- 点赞
- 收藏
- 关注作者
评论(0)