Ansible执行含重启操作的命令时如何获取任务标准输出?
Ansible执行含重启操作的命令时如何获取任务标准输出?
这种情况我之前也碰到过!核心问题在于:当远程主机因为重启主动断开SSH连接时,Ansible的SSH客户端没办法完整接收远程端已经产生的输出缓冲区内容——连接断得太突然,那些输出还没来得及传输到控制节点,所以注册的变量里就只剩连接失败的提示,看不到脚本执行的真实输出。
下面给你几个可行的解决方案,最推荐的是第一种:
最靠谱的方案:把脚本输出重定向到远程主机本地文件
既然连接断开会丢输出,那我们先把输出存到远程主机的本地文件里,等主机重启恢复后再去读取这个文件。
修改expect任务,添加输出重定向
把原来的command改成带重定向的形式,让脚本的标准输出和错误都写到本地日志文件:
- name: Launch installer script expect: command: "./install.sh > {{ installer_directory }}/install_output.log 2>&1" chdir: "{{ installer_directory }}" creates: "{{ product_base_directory }}/uninstall.sh" responses: "{{ sudo_password_prompt | items2dict}}" timeout: 1200 # 20 minutes ignore_errors: true ignore_unreachable: true register: install_script_output
这里的2>&1是把stderr也重定向到stdout的日志文件里,确保所有输出(包括错误信息)都被完整记录。
等待主机重启恢复,并读取日志文件
主机重启后,我们需要等它重新上线,然后用slurp或fetch模块获取日志内容:
- name: Wait for host to come back after reboot wait_for_connection: timeout: 300 # 5分钟足够大部分主机完成重启 - name: Read installer output from remote log file slurp: path: "{{ installer_directory }}/install_output.log" register: remote_log_content - name: Display full installer output debug: msg: "{{ remote_log_content.content | b64decode }}"
slurp模块会把文件内容以base64编码返回,所以需要用b64decode解码后才能正常显示。如果日志文件很大,也可以用fetch模块把文件下载到控制节点的本地目录。
为什么原来的方式拿不到输出?
当你的脚本执行完成触发重启时,远程主机的SSH服务会立刻终止所有活跃连接,这时候Ansible的SSH客户端还在等待后续输出,但连接已经被强制关闭了——远程端已经生成的输出可能还在缓冲区里没来得及发送,或者发送到一半就断了,所以这些内容根本没传到控制节点,自然不会出现在install_script_output变量里。而如果脚本执行失败没有触发重启,SSH连接是正常关闭的,Ansible就能完整接收所有输出。
其他可选方案(适用性有限)
- 调整SSH连接参数:可以尝试在
ansible.cfg里开启SSH的KeepAlive,比如设置ssh_args = -o ServerAliveInterval=30 -o ServerAliveCountMax=5,但这种方法对主动重启导致的连接断开效果很有限,只能碰碰运气。 - 后台执行+日志:如果脚本不需要交互(但你这里需要输入sudo密码,expect必须前台运行),可以用
nohup ./install.sh > install.log 2>&1 &,但这个方案对你的场景不适用。
备注:内容来源于stack exchange,提问作者Vlad Nikiforov
相关产品推荐
相关产品推荐

