在使用ansible的过程中,我们经常需要处理一些返回信息,而这些返回信息中,通常可能不是单独的一条返回信息,而是一个信息列表,如果我们想要循环的处理信息列表中的每一条信息,我们该怎么办呢?这样空口白话的描述有些费力,不如通过一些小示例,结合场景来描述。
以下是我的配置清单:
192.168.10.2 192.168.10.3 [group1] 192.168.10.10 [group2] 192.168.10.20 [group:children] group1 group2
我想获取配置清单中,没有分组的主机名,如下所示:
[root@ansible-control ansible]# ansible 192.168.10.2 -m debug -a "msg={{groups.ungrouped}}" 192.168.10.2 | SUCCESS => { "msg": [ "192.168.10.2", "192.168.10.3" ] }
现在我想获得未分组的主机名中第2台主机的主机名信息,如下所示:
注意[ ]里面的标签号计数是从0开始,第一台主机就是[0],第二台就是[1],依此类推
[root@ansible-control ansible]# ansible 192.168.10.2 -m debug -a "msg={{groups.ungrouped[1]}}" 192.168.10.2 | SUCCESS => { "msg": "192.168.10.2" }
但是问题是,我们通常不能确定返回信息有几条,我们可能需要循环的处理返回信息中的每一条信息,那么怎么才能循环处理返回信息中的每一条信息呢?示例playbook如下:
--- - hosts: 192.168.10.2 remote_user: root gather_facts: no tasks: - debug: msg: "{{item}}" with_items: "{{groups.ungrouped}}"
上例中,我们通过“{{groups.ungrouped}}”获取到了未分组的返回信息,并使用关键字with_items接收了返回信息,然后使用debug模块输出了名为item变量的变量值,聪明如你一定已经明白了, with_items 关键字会把返回的列表信息自动处理,将每一条信息单独放在一个名为 item 的变量中,我们只要获取到名为 item 变量的变量值,即可循环的获取到列表中的每一条信息,所以,上例中返回信息中的每一条信息都会循环的被debug模块处理,执行上述playbook后结果如下 :
从执行playbook的结果可以看出,debug模块对每条信息都单独输出了一次,而不是三条信息同时一次输出,由于对应play是针对192.168.10.2主机操作的,所以上例中debug模块的三次操作都是在该主机上进行的,只不过debug模块只是输出信息,并不会对该主机做出什么实际的改动而已,通过上述方法,就能够符合我们循环操作的要求了。
上例中,我们使用的是返回值中的信息,那么我们能不能自定义一个列表,然后循环使用列表中的值呢?必须能的,示例如下:
--- - hosts: 192.168.10.2 remote_user: root gather_facts: no tasks: - debug: msg: "{{item}}" with_items: - 1 - 2 - 3
如上例所示,我们自定义了3个值,分别是1、2、3,debug模块会循环的输出这三个值。
换一种写法,和上面的效果等效:
--- - hosts: 192.168.10.2 remote_user: root gather_facts: no tasks: - debug: msg: "{{item}}" with_items: [1,2,3]
定义一些稍微复杂的列表:
--- - hosts: 192.168.10.2 remote_user: root gather_facts: no tasks: - debug: msg: "{{item.test1}}" with_items: - { test1: a, test2: b } - { test1: c, test2: d }
上例中自定义列表中的每一个条目都是一个对象,我们可以通过对象的属性对应的 键 ,获取到对应的 值 ,如上例所示,第一个条目的test1键对应的值是a,第二个条目的test1键对应的值是c,所以执行上例playbook以后, a 和 c 会被输出。
工作生产中使用循环的实际案例:
如果想要在同一主机中创建四个文件,那么你可能会编写如下playbook:
--- - hosts: 192.168.10.2 remote_user: root gather_facts: no vars: dirs: - "/test/a" - "/test/b" - "/test/c" - "/test/d" tasks: - file: path: "{{item}}" state: touch with_items: "{{dirs}}"