Ansible如何在changed_when/failed_when中访问任务执行结果
问题根因
你遇到的报错通常由两个原因导致:
- 第一类是拼写错误:报错提示找不到
sterr属性,绝大多数情况是实际代码里把stderr(标准错误输出)少打了中间的字母d,拼写成了s-t-e-r-r,自然找不到对应属性。 - 如果确认所有地方拼写都是正确的,那问题出在异常场景的返回结构上:
failed_when和changed_when确实是在任务全流程执行完成后才评估的,不存在"执行中访问不到结果"的问题,但如果任务在shell命令实际运行前就失败了(比如SSH连接断开、become提权失败、模块前置校验不通过),返回的结果字典里根本不会生成stdout、stderr这两个只有命令执行才会返回的键,这时候直接用.stderr、.stdout访问属性就会报"不存在该属性"的错误。
你之前想的靠check_mode重复跑任务的方案完全没必要,冗余度太高。
优雅实现方式
直接用Jinja2的default过滤器给属性加空值兜底即可,同时补上shell模块默认的返回码校验逻辑,覆盖所有异常场景:
- name: Remove {{ atlassiandb }} database ansible.builtin.shell: cmd: "export VALUE='ABC' && echo $VALUE" register: shell_result become: yes failed_when: - shell_result.rc != 0 - "'ERROR' in (shell_result.stderr | default(''))" changed_when: "'abc' in (shell_result.stdout | default(''))"
写法说明
- 加上
shell_result.rc !=0判断是为了对齐shell模块默认的失败判定逻辑:命令返回码非0时直接判定失败,避免漏掉"命令执行异常但没输出ERROR字符串"的场景。 | default('')会在对应属性不存在时返回空字符串作为兜底,哪怕任务因为连接、提权问题提前失败,条件判断也能正常运行,不会抛属性不存在的错误。- 显式写全模块名
ansible.builtin.shell可以避免不同Ansible版本下的模块解析冲突,兼容性更好。
如果还是不确定属性名是否正确,可以临时把两个条件都设为false跑一次任务,用debug模块打印shell_result.keys(),直接看返回结果里实际包含哪些键,就能快速定位拼写问题。
内容的提问来源于stack exchange,提问作者MaestroGlanz
相关产品推荐
相关产品推荐

