Loading... <blockquote>在本博客中,ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。 ansible系列博文直达链接:<a href="https://www.zsythink.net/archives/tag/ansible/" target="_blank" rel="noopener">ansible轻松入门系列</a> “ansible系列”中的每篇文章都建立在前文的基础之上,所以,请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。</blockquote> 在使用ansible的过程中,我们经常需要处理一些返回信息,而这些返回信息中,通常可能不是单独的一条返回信息,而是一个信息列表,如果我们想要循环的处理信息列表中的每一条信息,我们该怎么办呢?这样空口白话的描述有些费力,不如通过一些小示例,结合场景来描述。 假设,我的清单配置如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">10.</span><span class="enlighter-m3">1</span><span class="enlighter-text">.</span><span class="enlighter-n0">1.60</span></div> </div> <div class=""> <div><span class="enlighter-text">test70.</span><span class="enlighter-m3">zsythink</span><span class="enlighter-text">.</span><span class="enlighter-m3">net</span><span class="enlighter-text"> ansible_host=</span><span class="enlighter-n0">10.1</span><span class="enlighter-text">.</span><span class="enlighter-n0">1.70</span></div> </div> <div class=""> <div><span class="enlighter-text">test71 anisble_host=</span><span class="enlighter-n0">10.1</span><span class="enlighter-text">.</span><span class="enlighter-n0">1.71</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">[</span><span class="enlighter-text">testA</span><span class="enlighter-g1">]</span></div> </div> <div class=""> <div><span class="enlighter-text">test60 ansible_host=</span><span class="enlighter-n0">10.1</span><span class="enlighter-text">.</span><span class="enlighter-n0">1.60</span></div> </div> <div class=""> <div><span class="enlighter-text">test61 ansible_host=</span><span class="enlighter-n0">10.1</span><span class="enlighter-text">.</span><span class="enlighter-n0">1.61</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">[</span><span class="enlighter-text">testB</span><span class="enlighter-g1">]</span></div> </div> <div class=""> <div><span class="enlighter-text">test70 ansible_host=</span><span class="enlighter-n0">10.1</span><span class="enlighter-text">.</span><span class="enlighter-n0">1.70</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">[</span><span class="enlighter-text">test:children</span><span class="enlighter-g1">]</span></div> </div> <div class=""> <div><span class="enlighter-text">testA</span></div> </div> <div class=""> <div><span class="enlighter-text">testB</span></div> </div> </div> </div> 如果我想要获取到清单中所有未分组的主机的主机名,则可以执行如下命令 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># ansible test70 -m debug -a "msg={{groups.ungrouped}}"</span></div> </div> <div class=""> <div><span class="enlighter-text">test70 </span><span class="enlighter-g0">|</span><span class="enlighter-text"> SUCCESS =</span><span class="enlighter-g1">></span> <span class="enlighter-g1">{</span></div> </div> <div class=""> <div><span class="enlighter-s0">"changed"</span><span class="enlighter-text">: </span><span class="enlighter-k1">false</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"msg"</span><span class="enlighter-text">: </span><span class="enlighter-g1">[</span></div> </div> <div class=""> <div><span class="enlighter-s0">"10.1.1.60"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"test70.zsythink.net"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"test71"</span></div> </div> <div class=""> <div><span class="enlighter-g1">]</span></div> </div> <div class=""> <div><span class="enlighter-g1">}</span></div> </div> </div> </div> 从返回信息可以看出,一共有3个未分组主机,上例的返回信息中就不只有一条信息记录,如果我们想要获取到上述返回信息中的第二条信息,则可以使用如下方法 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># ansible test70 -m debug -a "msg={{groups.ungrouped[1]}}"</span></div> </div> <div class=""> <div><span class="enlighter-text">test70 </span><span class="enlighter-g0">|</span><span class="enlighter-text"> SUCCESS =</span><span class="enlighter-g1">></span> <span class="enlighter-g1">{</span></div> </div> <div class=""> <div><span class="enlighter-s0">"changed"</span><span class="enlighter-text">: </span><span class="enlighter-k1">false</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"msg"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"test70.zsythink.net"</span></div> </div> <div class=""> <div><span class="enlighter-g1">}</span></div> </div> </div> </div> 但是问题是,我们通常不能确定返回信息有几条,我们可能需要循环的处理返回信息中的每一条信息,那么怎么才能循环处理返回信息中的每一条信息呢?示例playbook如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> remote_user: root</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - debug:</span></div> </div> <div class=""> <div><span class="enlighter-text"> msg: </span><span class="enlighter-s0">"{{item}}"</span></div> </div> <div class=""> <div><span class="enlighter-text"> with_items: </span><span class="enlighter-s0">"{{groups.ungrouped}}"</span></div> </div> </div> </div> 上例中,我们通过”{{groups.ungrouped}}”获取到了未分组的返回信息,并使用关键字”with_items”接收了返回信息,然后使用debug模块输出了名为”item”变量的变量值,聪明如你一定已经明白了,”with_items”关键字会把返回的列表信息自动处理,将每一条信息单独放在一个名为”item”的变量中,我们只要获取到名为”item”变量的变量值,即可循环的获取到列表中的每一条信息,所以,上例中返回信息中的每一条信息都会循环的被debug模块处理,执行上述playbook后结果如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">TASK </span><span class="enlighter-g1">[</span><span class="enlighter-text">debug</span><span class="enlighter-g1">]</span> <span class="enlighter-g0">*********************************************</span></div> </div> <div class=""> <div><span class="enlighter-text">ok: </span><span class="enlighter-g1">[</span><span class="enlighter-text">test70</span><span class="enlighter-g1">]</span><span class="enlighter-text"> =</span><span class="enlighter-g1">></span> <span class="enlighter-g1">(</span><span class="enlighter-text">item=</span><span class="enlighter-n0">10.1</span><span class="enlighter-text">.</span><span class="enlighter-n0">1.60</span><span class="enlighter-g1">)</span><span class="enlighter-text"> =</span><span class="enlighter-g1">></span> <span class="enlighter-g1">{</span></div> </div> <div class=""> <div><span class="enlighter-s0">"changed"</span><span class="enlighter-text">: </span><span class="enlighter-k1">false</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"item"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"10.1.1.60"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"msg"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"10.1.1.60"</span></div> </div> <div class=""> <div><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text">ok: </span><span class="enlighter-g1">[</span><span class="enlighter-text">test70</span><span class="enlighter-g1">]</span><span class="enlighter-text"> =</span><span class="enlighter-g1">></span> <span class="enlighter-g1">(</span><span class="enlighter-text">item=test70.</span><span class="enlighter-m3">zsythink</span><span class="enlighter-text">.</span><span class="enlighter-m3">net</span><span class="enlighter-g1">)</span><span class="enlighter-text"> =</span><span class="enlighter-g1">></span> <span class="enlighter-g1">{</span></div> </div> <div class=""> <div><span class="enlighter-s0">"changed"</span><span class="enlighter-text">: </span><span class="enlighter-k1">false</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"item"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"test70.zsythink.net"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"msg"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"test70.zsythink.net"</span></div> </div> <div class=""> <div><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text">ok: </span><span class="enlighter-g1">[</span><span class="enlighter-text">test70</span><span class="enlighter-g1">]</span><span class="enlighter-text"> =</span><span class="enlighter-g1">></span> <span class="enlighter-g1">(</span><span class="enlighter-text">item=test71</span><span class="enlighter-g1">)</span><span class="enlighter-text"> =</span><span class="enlighter-g1">></span> <span class="enlighter-g1">{</span></div> </div> <div class=""> <div><span class="enlighter-s0">"changed"</span><span class="enlighter-text">: </span><span class="enlighter-k1">false</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"item"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"test71"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"msg"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"test71"</span></div> </div> <div class=""> <div><span class="enlighter-g1">}</span></div> </div> </div> </div> 从执行playbook的结果可以看出,debug模块对每条信息都单独输出了一次,而不是三条信息同时一次输出,由于对应play是针对test70主机操作的,所以上例中debug模块的三次操作都是在test70主机上进行的,只不过debug模块只是输出信息,并不会对test70主机做出什么实际的改动而已,通过上述方法,就能够符合我们循环操作的要求了。 上例中,我们使用的是返回值中的信息,那么我们能不能自定义一个列表,然后循环使用列表中的值呢?必须能的,示例如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> remote_user: root</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - debug:</span></div> </div> <div class=""> <div><span class="enlighter-text"> msg: </span><span class="enlighter-s0">"{{item}}"</span></div> </div> <div class=""> <div><span class="enlighter-text"> with_items:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-n1">1</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-n1">2</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-n1">3</span></div> </div> </div> </div> 如上例所示,我们自定义了3个值,分别是1、2、3,debug模块会循环的输出这三个值。 或者我们换一种写法,如下写法与上述写法的效果完全相同。 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> remote_user: root</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - debug:</span></div> </div> <div class=""> <div><span class="enlighter-text"> msg: </span><span class="enlighter-s0">"{{item}}"</span></div> </div> <div class=""> <div><span class="enlighter-text"> with_items: </span><span class="enlighter-g1">[</span> <span class="enlighter-n1">1</span><span class="enlighter-text">, </span><span class="enlighter-n1">2</span><span class="enlighter-text">, </span><span class="enlighter-n1">3</span> <span class="enlighter-g1">]</span></div> </div> </div> </div> 我们还能够自定义稍微复杂些的列表,示例如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> remote_user: root</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - debug:</span></div> </div> <div class=""> <div><span class="enlighter-text"> msg: </span><span class="enlighter-s0">"{{item.test1}}"</span></div> </div> <div class=""> <div><span class="enlighter-text"> with_items:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-g1">{</span><span class="enlighter-text"> test1: a, test2: b </span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-g1">{</span><span class="enlighter-text"> test1: c, test2: d </span><span class="enlighter-g1">}</span></div> </div> </div> </div> 上例中自定义列表中的每一个条目都是一个对象,我们可以通过对象的属性对应的”键”,获取到对应的”值”,如上例所示,第一个条目的test1键对应的值是a,第二个条目的test1键对应的值是c,所以执行上例playbook以后,”a”和”c”会被输出。 学会使用循环,能够让我们事半功倍。 比如,在没有学会使用循环之前,如果想要在同一主机中创建四个文件,那么你可能会编写如下playbook <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> remote_user: root</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - file:</span></div> </div> <div class=""> <div><span class="enlighter-text"> path: </span><span class="enlighter-s0">"/opt/a"</span></div> </div> <div class=""> <div><span class="enlighter-text"> state: touch</span></div> </div> <div class=""> <div><span class="enlighter-text"> - file:</span></div> </div> <div class=""> <div><span class="enlighter-text"> path: </span><span class="enlighter-s0">"/opt/b"</span></div> </div> <div class=""> <div><span class="enlighter-text"> state: touch</span></div> </div> <div class=""> <div><span class="enlighter-text"> - file:</span></div> </div> <div class=""> <div><span class="enlighter-text"> path: </span><span class="enlighter-s0">"/opt/c"</span></div> </div> <div class=""> <div><span class="enlighter-text"> state: touch</span></div> </div> <div class=""> <div><span class="enlighter-text"> - file:</span></div> </div> <div class=""> <div><span class="enlighter-text"> path: </span><span class="enlighter-s0">"/opt/d"</span></div> </div> <div class=""> <div><span class="enlighter-text"> state: touch</span></div> </div> </div> </div> 我们重复的书写了file模块4次,其实每次只是改变了file模块的path参数的值而已,如果使用循环,上例的playbook则可以改写成如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> remote_user: root</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> vars:</span></div> </div> <div class=""> <div><span class="enlighter-text"> dirs:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"/opt/a"</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"/opt/b"</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"/opt/c"</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"/opt/d"</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - file:</span></div> </div> <div class=""> <div><span class="enlighter-text"> path: </span><span class="enlighter-s0">"{{item}}"</span></div> </div> <div class=""> <div><span class="enlighter-text"> state: touch</span></div> </div> <div class=""> <div><span class="enlighter-text"> with_items: </span><span class="enlighter-s0">"{{dirs}}"</span></div> </div> </div> </div> 正如上述示例所示,重复的操作越多,使用循环则越方便。 那么我们再来看一个小示例,这个示例与循环没有直接关系,但是可以引出我们要说的话题,示例playbook如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - shell: </span><span class="enlighter-s0">"ls /opt"</span></div> </div> <div class=""> <div><span class="enlighter-text"> register: returnvalue</span></div> </div> <div class=""> <div><span class="enlighter-text"> - debug:</span></div> </div> <div class=""> <div><span class="enlighter-text"> var: returnvalue</span></div> </div> </div> </div> 看到上例,你一定不会觉得陌生,在之前总结变量的文章中,我们已经总结过”register”的用法,我们可以通过”register”获取到模块执行后的”返回值”信息,如果你忘记了”register”的用法,请回顾<a href="https://www.zsythink.net/archives/2680" target="_blank" rel="noopener">前文</a>,上例中,我们将shell模块执行后的返回值写入了名为”returnvalue”的变量中,然后使用debug模块输出了”returnvalue”变量的值,上述playbook执行后结果如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">TASK </span><span class="enlighter-g1">[</span><span class="enlighter-text">debug</span><span class="enlighter-g1">]</span> <span class="enlighter-g0">******************</span></div> </div> <div class=""> <div><span class="enlighter-text">ok: </span><span class="enlighter-g1">[</span><span class="enlighter-text">test70</span><span class="enlighter-g1">]</span><span class="enlighter-text"> =</span><span class="enlighter-g1">></span> <span class="enlighter-g1">{</span></div> </div> <div class=""> <div><span class="enlighter-s0">"returnvalue"</span><span class="enlighter-text">: </span><span class="enlighter-g1">{</span></div> </div> <div class=""> <div><span class="enlighter-s0">"changed"</span><span class="enlighter-text">: </span><span class="enlighter-k1">true</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"cmd"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"ls /opt"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"delta"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"0:00:01.006690"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"end"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"2018-07-12 17:43:01.445936"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"failed"</span><span class="enlighter-text">: </span><span class="enlighter-k1">false</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"rc"</span><span class="enlighter-text">: </span><span class="enlighter-n1">0</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"start"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"2018-07-12 17:43:00.439246"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"stderr"</span><span class="enlighter-text">: </span><span class="enlighter-s0">""</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"stderr_lines"</span><span class="enlighter-text">: </span><span class="enlighter-g1">[]</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"stdout"</span><span class="enlighter-text">: </span><span class="enlighter-s0">"rh"</span><span class="enlighter-text">,</span></div> </div> <div class=""> <div><span class="enlighter-s0">"stdout_lines"</span><span class="enlighter-text">: </span><span class="enlighter-g1">[</span></div> </div> <div class=""> <div><span class="enlighter-s0">"rh"</span></div> </div> <div class=""> <div><span class="enlighter-g1">]</span></div> </div> <div class=""> <div><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">}</span></div> </div> </div> </div> 可以看到shell模块的返回值信息如上,但是,上例并没有借助循环重复调用shell模块,如果使用循环多次调用shell模块执行不同的命令,返回信息的格式还会和原来一样吗?我们来实验一下,我们将上例的playbook修改如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - shell: </span><span class="enlighter-s0">"{{item}}"</span></div> </div> <div class=""> <div><span class="enlighter-text"> with_items:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"ls /opt"</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"ls /home"</span></div> </div> <div class=""> <div><span class="enlighter-text"> register: returnvalue</span></div> </div> <div class=""> <div><span class="enlighter-text"> - debug:</span></div> </div> <div class=""> <div><span class="enlighter-text"> var: returnvalue</span></div> </div> </div> </div> 如上例所示,我们使用循环重复调用了shell模块两次,分别执行了两条命令,然后将shell模块的返回值存放到了”returnvalue”变量中,最后使用debug模块输出了”returnvalue”变量的值,那么当我们使用循环时,返回值信息会和原来一样么?上例的playbook执行后debug模块的输出如下 <img class=" lazyloaded" src="https://www.zsythink.net/wp-content/uploads/2018/07/071318_0923_1.png" alt="" data-src="https://www.zsythink.net/wp-content/uploads/2018/07/071318_0923_1.png" style=""> 细心如你一定发现了,当使用了循环以后,每次shell模块执行后的返回值都会放入一个名为”results”的序列中,其实,”results”也是一个返回值,当模块中使用了循环时,模块每次执行的返回值都会追加存放到”results”这个返回值中,所以,我们可以通过”results”关键字获取到每次模块执行后的返回值,示例如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - shell: </span><span class="enlighter-s0">"{{item}}"</span></div> </div> <div class=""> <div><span class="enlighter-text"> with_items:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"ls /opt"</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"ls /home"</span></div> </div> <div class=""> <div><span class="enlighter-text"> register: returnvalue</span></div> </div> <div class=""> <div><span class="enlighter-text"> - debug:</span></div> </div> <div class=""> <div><span class="enlighter-text"> msg: </span><span class="enlighter-s0">"{{item.stdout}}"</span></div> </div> <div class=""> <div><span class="enlighter-text"> with_items: </span><span class="enlighter-s0">"{{returnvalue.results}}"</span></div> </div> </div> </div> 上例中,我们先使用循环重复的调用了shell模块,然后将shell模块每次执行后的返回值注册到了变量”returnvalue”中,之后,在使用debug模块时,通过返回值”results”获取到了之前每次执行shell模块的返回值(shell每次执行后的返回值已经被放入到item变量中),最后又通过返回值”stdout”获取到了每次shell模块执行后的标准输出,你可以执行一下上例的playbook,执行后,输出结果的msg关键字对应的值就是每次shell模块执行后的标准输出。 你可能还会看到有的朋友使用如下方法输出”{{returnvalue.results}}”列表中的信息 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">---</span></div> </div> <div class=""> <div><span class="enlighter-text">- hosts: test70</span></div> </div> <div class=""> <div><span class="enlighter-text"> gather_facts: no</span></div> </div> <div class=""> <div><span class="enlighter-text"> tasks:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - shell: </span><span class="enlighter-s0">"{{item}}"</span></div> </div> <div class=""> <div><span class="enlighter-text"> with_items:</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"ls /opt"</span></div> </div> <div class=""> <div><span class="enlighter-text"> - </span><span class="enlighter-s0">"ls /home"</span></div> </div> <div class=""> <div><span class="enlighter-text"> register: returnvalue</span></div> </div> <div class=""> <div><span class="enlighter-text"> - debug:</span></div> </div> <div class=""> <div><span class="enlighter-text"> msg:</span></div> </div> <div class=""> <div><span class="enlighter-s0">"{% for i in returnvalue.results %}</span></div> </div> <div class=""> <div><span class="enlighter-s0"> {{ i.stdout }}</span></div> </div> <div class=""> <div><span class="enlighter-s0"> {% endfor %}"</span></div> </div> </div> </div> 你一定看出来了,上例使用了一个for循环遍历了” returnvalue.results”列表,上例中for循环的语法为jinja2语言中的for循环语法,jinja2是一种模板语言,jinja2是一个基于python的模板引擎,所以,在ansible中,我们可以使用jinja2编写模板文件,然后再根据模板文件来生成配置文件,jinja2中也有一些控制语句结构,比如for循环,上例中使用的就是jinja2语法中的for循环,如果你执行了上例的playbook,你会发现,debug模块只执行了一次,msg中对应的信息是所有shell模块执行后的stdout返回值,因为debug模块只是输出了经过jinja2的for循环处理过的信息而已,debug模块并没有因为for循环而被重复的调用。如果你对jinja2的语法不是很了解,不用在意,此处只是展示一个小示例,当我们总结模板的用法时,再去了解jinja2相应的使用方法也不迟,所以看不懂也不用纠结。 这篇文章就总结到这里,希望能够对你有所帮助~ 转载自朱双印日志https://www.zsythink.net/archives/2728 Last modification:May 29, 2024 © Allow specification reprint Like 如果觉得我的文章对你有用,请随意赞赏