Ansible中使用failed_when处理错误失效问题求助
解决Ansible循环中failed_when触发错误的问题
你的问题出在循环任务中register变量的结构上。当你使用with_items(或loop)时,register: output得到的不是单个任务的结果,而是一个包含所有迭代结果的集合——其中output.results是一个列表,每个元素对应一个服务的执行结果。而你直接引用output.rc是错误的,因为这个顶层变量根本没有rc字段,导致你的failed_when条件始终为真(未定义的变量和0/1比较都会返回true),所以剧本会触发失败。
修正方案1:正确引用循环中的单个结果
在Ansible 2.5及以上版本,可以使用ansible_loop.result来访问当前迭代的任务结果,把failed_when改成针对每个服务的返回码判断:
- hosts: server_group1 remote_user: ansible tasks: - name: Stop services command: /bin/systemctl stop "{{ item }}" with_items: - cups - avahi - slapd - isc-dhcp-server - isc-dhcp-server6 - nfs-server - rpcbind - bind9 - vsftpd - dovecot - smbd - snmpd - squid register: output failed_when: ansible_loop.result.rc not in [0, 1]
如果你的Ansible版本低于2.5,可以使用result.rc(旧版本中循环内的单个结果变量):
failed_when: result.rc not in [0, 1]
修正方案2:使用Ansible原生systemd模块(更推荐)
直接用command调用systemctl并不是最佳实践,Ansible提供了systemd模块来更优雅地管理系统服务,还能直接处理服务不存在或已停止的场景:
- hosts: server_group1 remote_user: ansible tasks: - name: Stop and disable unwanted services systemd: name: "{{ item }}" state: stopped enabled: no with_items: - cups - avahi - slapd - isc-dhcp-server - isc-dhcp-server6 - nfs-server - rpcbind - bind9 - vsftpd - dovecot - smbd - snmpd - squid # 忽略服务不存在的错误(如果某些机器没装这些服务) failed_when: "'Could not find the requested service' not in ansible_loop.result.msg and ansible_loop.result.failed"
这个模块会自动处理服务已停止的情况,返回成功;如果服务不存在,你可以通过failed_when来过滤掉这种场景,避免剧本失败。
为什么ignore_errors: true能工作?
当你添加ignore_errors: true时,Ansible会忽略所有任务失败的情况,包括你错误的failed_when判断导致的失败,但这只是治标不治本的方法——正确引用循环结果才是解决问题的根本。
内容的提问来源于stack exchange,提问作者Tux_and_gone
相关产品推荐
相关产品推荐

