You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 06:10:59