我想在Ansible中使用以下处理程序:
- name: force ntp update
shell: ntpdate {{item}}
with_lines: /etc/ntpd.serverlist
但我希望它在第一次成功执行后结束执行(该列表包含可以尝试同步的ntpd服务器。一个就足够了)。我该怎么做?
答案 0 :(得分:4)
至少在Ansible 2.2.1.0上,when
语句可以打破循环,以下工作在第一次成功后跳过所有评估:
---
# test.yml
# run this playbook with: ansible-playbook -i localhost, test.yml
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: check
shell: "[ {{item}} -ne 2 ]"
register: checks
ignore_errors: yes
changed_when: false
when: checks is not defined or checks.rc != 0
with_items: [2,3,2,4]
- name: set
set_fact: first_working={{ item.item }}
when: "'rc' in item and item.rc == 0"
with_items: "{{ checks.results }}"
- debug: var=first_working
# Note that first_working will be undefined if no check succeeded
这是输出:
PLAY [localhost] ***************************************************************
TASK [check] *******************************************************************
failed: [localhost] (item=2) => {"changed": false, "cmd": "[ 2 -ne 2 ]", "delta": "0:00:00.001735", "end": "2017-03-13 16:14:00.515372", "failed": true, "item": 2, "rc": 1, "start": "2017-03-13 16:14:00.513637", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": []}
ok: [localhost] => (item=3)
skipping: [localhost] => (item=2)
skipping: [localhost] => (item=4)
...ignoring
TASK [set] *********************************************************************
skipping: [localhost] => (item={'_ansible_parsed': True, u'cmd': u'[ 2 -ne 2 ]', u'end': u'2017-03-13 16:14:00.515372', '_ansible_no_log': False, u'stdout': u'', '_ansible_item_result': True, u'changed': False, 'item': 2, u'delta': u'0:00:00.001735', u'stderr': u'', u'rc': 1, 'invocation': {'module_name': u'command', u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': True, u'_raw_params': u'[ 2 -ne 2 ]', u'removes': None, u'warn': True, u'chdir': None}}, 'stdout_lines': [], u'start': u'2017-03-13 16:14:00.513637', u'warnings': [], 'failed': True})
ok: [localhost] => (item={'_ansible_parsed': True, u'changed': False, u'stdout': u'', '_ansible_no_log': False, u'warnings': [], '_ansible_item_result': True, u'rc': 0, u'end': u'2017-03-13 16:14:00.615658', u'start': u'2017-03-13 16:14:00.613978', u'cmd': u'[ 3 -ne 2 ]', 'item': 3, u'delta': u'0:00:00.001680', 'invocation': {'module_name': u'command', u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': True, u'_raw_params': u'[ 3 -ne 2 ]', u'removes': None, u'warn': True, u'chdir': None}}, 'stdout_lines': [], u'stderr': u''})
skipping: [localhost] => (item={'skipped': True, '_ansible_no_log': False, 'skip_reason': u'Conditional check failed', '_ansible_item_result': True, 'item': 2, 'changed': False})
skipping: [localhost] => (item={'skipped': True, '_ansible_no_log': False, 'skip_reason': u'Conditional check failed', '_ansible_item_result': True, 'item': 4, 'changed': False})
TASK [debug] *******************************************************************
ok: [localhost] => {
"first_working": "3"
}
答案 1 :(得分:2)
这是一个非常有趣的情况。我个人没试过,但我想知道这样的事情是否有效:
- name: force ntp update
shell: ntpdate {{item}}
with_lines: /etc/ntpd.serverlist
register: ntp_result
when: ntp_result is not defined or ntp_result.rc != 0
ignore_errors: yes
因此,简而言之,每次调用ntpdate时都应使用ntp_result
调用的返回码填充ntpdate
变量。如果变量不存在(因为它在第一次迭代期间没有填充),或者when
调用失败(rc!= 0),ntpdate
子句将确保循环继续。告诉Ansible忽略任何错误,确保在ntpdate
的任何调用确实返回错误时继续循环。
唯一真正的缺点是,如果ntpdate
的所有呼叫均未成功,它将不会直接通知您。但是,您可以按照以下方式执行此任务:
- name: fail if ntpdate fails
fail: msg="All calls to ntpdate failed"
when: ntp_result.rc != 0
如果最后一次调用导致ntpdate
的结果为非零,则意味着它们都没有成功。