我有一个任务来验证所有Linux服务器的一些路由条目,这是我使用Ansible playbook的方式
---
- hosts: Linux
serial: 1
tasks:
- name: Check first
command: /sbin/ip route list xxx.xxx.xxx.xxx/24
register: result
changed_when: false
- debug: msg="{{result.stdout}}"
- name: Check second
command: /sbin/ip route list xxx.xxx.xxx.xxx/24
register: result
changed_when: false
- debug: msg="{{result.stdout}}"
你可以看到我必须为每个路由条目重复相同的任务,我相信我应该能够避免这种情况。我尝试使用with_items
循环,但得到了以下错误消息
One or more undefined variables: 'dict object' has no attribute 'stdout'
有没有办法为每个命令注册变量并逐个循环它们?
答案 0 :(得分:32)
从Ansible 1.6.1开始,使用多个项目注册的结果作为数组存储在result.results
中。所以你可以使用result.results[0].stdout
等等。
测试剧本:
---
- hosts: localhost
gather_facts: no
tasks:
- command: "echo {{item}}"
register: result
with_items: [1, 2]
- debug:
var: result
结果:
$ ansible-playbook -i localhost, test.yml
PLAY [localhost] **************************************************************
TASK: [command echo {{item}}] *************************************************
changed: [localhost] => (item=1)
changed: [localhost] => (item=2)
TASK: [debug ] ****************************************************************
ok: [localhost] => {
"var": {
"result": {
"changed": true,
"msg": "All items completed",
"results": [
{
"changed": true,
"cmd": [
"echo",
"1"
],
"delta": "0:00:00.002502",
"end": "2015-08-07 16:44:08.901313",
"invocation": {
"module_args": "echo 1",
"module_name": "command"
},
"item": 1,
"rc": 0,
"start": "2015-08-07 16:44:08.898811",
"stderr": "",
"stdout": "1",
"stdout_lines": [
"1"
],
"warnings": []
},
{
"changed": true,
"cmd": [
"echo",
"2"
],
"delta": "0:00:00.002516",
"end": "2015-08-07 16:44:09.038458",
"invocation": {
"module_args": "echo 2",
"module_name": "command"
},
"item": 2,
"rc": 0,
"start": "2015-08-07 16:44:09.035942",
"stderr": "",
"stdout": "2",
"stdout_lines": [
"2"
],
"warnings": []
}
]
}
}
}
PLAY RECAP ********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
答案 1 :(得分:5)
略有不同的情况,需要一段时间来弄清楚。如果你想使用多个项的结果,但对于changed_when
,那么寄存器变量将没有var.results!而是针对每个项目评估changed_when
,您可以直接使用寄存器var。
简单示例,将导致更改:false:
- action: command echo {{item}}
register: out
changed_when: "'z' in out.stdout"
with_items:
- hello
- foo
- bye
另一个例子:
- name: Create fulltext index for faster text searches.
mysql_db: name={{SO_database}} state=import target=/tmp/fulltext-{{item.tableName}}-{{item.columnName}}.sql
with_items:
- {tableName: Posts, columnName: Title}
- {tableName: Posts, columnName: Body}
- {tableName: Posts, columnName: Tags}
- {tableName: Comments, columnName: Text}
register: createfulltextcmd
changed_when: createindexcmd.msg.find('already exists') == -1
最后,当你想要在其他上下文中循环结果时,以编程方式访问索引似乎有点棘手,因为它没有公开。我确实找到了一个可能有希望的例子:
- name: add hosts to known_hosts
shell: 'ssh-keyscan -H {{item.host}}>> /home/testuser/known_hosts'
with_items:
- { index: 0, host: testhost1.test.dom }
- { index: 1, host: testhost2.test.dom }
- { index: 2, host: 192.168.202.100 }
when: ssh_known_hosts.results[{{item.index}}].rc == 1
答案 2 :(得分:0)
发帖,因为我无法发表评论
关于gameweld的答案,由于Ansible 2.5,因此还有另一种访问迭代索引的方法。
来自docs:
通过index_var循环跟踪进度
2.5版中的新功能。
要跟踪循环的位置,请使用index_var指令 与loop_control。该指令指定要包含的变量名称 当前循环索引:
- name: count our fruit debug: msg: "{{ item }} with index {{ my_idx }}" loop: - apple - banana - pear loop_control: index_var: my_idx
这还允许您从数组中收集结果,并在以后考虑到以前的结果的情况下对同一数组进行操作
- name: Ensure directories exist
file:
path: "{{ item }}"
state: directory
loop:
- "mouse"
- "lizard"
register: reg
- name: Do something only if directory is new
debug:
msg: "New dir created with name '{{ item }}'"
loop:
- "mouse"
- "lizard"
loop_control:
index_var: index
when: reg.results[index].changed
请注意,“鼠标蜥蜴”数组应该完全相同
答案 3 :(得分:-3)
如果您需要分别注册两个命令的输出,请使用不同的变量名称。
---
- hosts: Linux
serial: 1
tasks:
- name: Check first
command: /sbin/ip route list xxx.xxx.xxx.xxx/24
register: result0
changed_when: false
- debug: msg="{{result0.stdout}}"
- name: Check second
command: /sbin/ip route list xxx.xxx.xxx.xxx/24
register: result1
changed_when: false
- debug: msg="{{result1.stdout}}"