Ansible补丁升级任务报错:如何实现等待远程主机重启提示?
解决Ansible补丁升级任务中
stdout属性缺失的问题 问题场景
我想用Ansible自动化完成服务器补丁升级,编写了如下Playbook:
- name: Patch Upgrade block: - name: Patch upgrade process ansible.netcommon.cli_command: command: patch install {{ node_patch }} patches_repository check_all: True prompt: - "[yes] ?" - "[yes] ?" answer: - 'yes' - 'yes' register: result until: result.stdout.find("The system is going down for reboot NOW") != -1
补丁升级时的输出如下:
ISE/admin#patch install ise-patchbundle-10.1.0.0-Ptach3-19110111.SPA.x86_64.tar.gz FTP_repository % Warning: Patch installs only on this node. Install with Primary Administration node GUI to install on all nodes in deployment. Continue? (yes/no) [yes] ? yes Save the current ADE-OS run configuration? (yes/no) [yes] ? yes Generating configuration... Saved the ADE-OS run Configuration to startup successfully Initiating Application Patch installation... Getting bundle to local machine... Unbundling Application Package... Verifying Application Signature... patch successfully installed % This application Install or Upgrade requires reboot, rebooting now... Broadcast message from root@ISE (pts/1) (Fri Feb 14 01:06:21 2020): Trying to stop processes gracefully. Reload lasts approximately 3 mins Broadcast message from root@ISE (pts/1) (Fri Feb 14 01:06:21 2020): Trying to stop processes gracefully. Reload takes approximately 3 mins Broadcast message from root@ISE (pts/1) (Fri Feb 14 01:06:41 2020): The system is going down for reboot NOW Broadcast message from root@ISE (pts/1) (Fri Feb 14 01:06:41 2020): The system is going down for reboot NOW
我的需求是让任务持续运行,直到收到The system is going down for reboot NOW这一行后,再执行等待主机恢复的后续任务。但执行失败,报错信息如下:
fatal: [serv-1]: FAILED! => msg: 'The conditional check ''result.stdout.find("The system is going down for reboot NOW") != -1'' failed. The error was: error while evaluating conditional (result.stdout.find("The system is going down for reboot NOW") != -1): ''dict object'' has no attribute ''stdout'''
解决方案
1. 补全条件判断的前置检查
报错核心原因是第一次执行cli_command后,返回的result对象可能还未生成stdout属性,或者服务器重启前模块连接中断导致stdout未被正确捕获。需要先判断属性是否存在再进行字符串匹配:
until: result is defined and result.stdout is defined and result.stdout.find("The system is going down for reboot NOW") != -1
2. 改用stdout_lines匹配更可靠
由于输出是逐行返回的,用stdout_lines列表检查目标字符串是否存在会更直观,也能避免部分场景下stdout拼接不完整的问题:
until: result is defined and result.stdout_lines is defined and "The system is going down for reboot NOW" in result.stdout_lines
3. 配置合理的重试参数
补丁升级无固定时长,必须给until循环设置足够的重试次数和间隔,避免因等待时间不足导致任务失败:
- name: Patch upgrade process ansible.netcommon.cli_command: command: patch install {{ node_patch }} patches_repository check_all: True prompt: - "[yes] ?" - "[yes] ?" answer: - 'yes' - 'yes' register: result until: result is defined and result.stdout_lines is defined and "The system is going down for reboot NOW" in result.stdout_lines retries: 30 # 根据实际升级时长调整 delay: 10 # 每次重试间隔10秒
4. 忽略重启导致的连接中断错误
当服务器开始重启时,SSH连接会被强制断开,cli_command模块会返回失败状态,但此时我们已经拿到了重启提示。可以通过failed_when来过滤这种情况:
- name: Patch upgrade process ansible.netcommon.cli_command: command: patch install {{ node_patch }} patches_repository check_all: True prompt: - "[yes] ?" - "[yes] ?" answer: - 'yes' - 'yes' register: result failed_when: > (result.failed is defined and result.failed) and not (result.stdout_lines is defined and "The system is going down for reboot NOW" in result.stdout_lines) until: result is defined and result.stdout_lines is defined and "The system is going down for reboot NOW" in result.stdout_lines retries: 30 delay: 10
这样即使连接中断,只要输出中包含重启提示,任务就不会被标记为失败。
内容的提问来源于stack exchange,提问作者sumaaiiiaaaa
相关产品推荐
相关产品推荐

