金鱼哥说Ansible:第五章 实施任务控制---编写循环任务

举报
金鱼哥 发表于 2022/04/10 09:38:20 2022/04/10
【摘要】 快捷玩Ansible循环任务

快捷玩Ansible循环任务

IT民工金鱼哥希望能以通俗易懂、诙谐幽默的方式把Ansible体系文章呈现给大家,让枯燥的知识点、让繁重的学习变的有趣一些。

某金鱼小弟闯荡江湖一段时日,于某日发现其所学Ansible的招式不够应对二、三流门派的鱼虾蟹(突然一个声音:这么水吗?),故而闭关修炼。沉思如何做掉这些曾欺负过他的人,忽然天上一闪,一招“循环”招式植入脑海,于是乎马上演练:

2222

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,人家是比翼双飞,水影鸳鸾 >.<)

image-20211210000200243

较早样式的循环关键字

在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搞掂。)

333

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

44

💡总结

  • 理解Ansible循环任务的使用场景。
  • 运用loop与item编写循环任务。
  • 理解循环任务与注册变量的搭配。

以上就是【金鱼哥】对 第五章 实施任务控制----编写循环任务 的简述和讲解。希望能对看到此文章的小伙伴有所帮助。

如果这篇【文章】有帮助到你,希望可以给【金鱼哥】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【运维技术】感兴趣,也欢迎关注❤️❤️❤️ 【金鱼哥】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!

111

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。