通过Bash脚本批量重启远程服务器如何避免手动干预?
解决批量重启远程服务器时SSH Broken Pipe及手动回车问题
当执行ssh -t $host "sudo reboot -f now"后,服务器会立即终止SSH服务触发连接断开,本地SSH客户端会抛出packet_write_wait: Connection to ... port 22: Broken pipe提示,再加上-t参数分配的伪终端会因连接断开进入半阻塞状态,导致脚本需要手动回车才能继续。以下是几种无干预的解决方法:
方案1:后台执行重启命令并立即断开SSH会话
如果已配置免密sudo(避免输入密码卡住脚本),可以去掉-t参数,将重启命令放到后台执行并重定向输出,让SSH会话直接结束:
for host in server1 server2; do echo "Restarting $host..." ssh $host "sudo nohup reboot -f now > /dev/null 2>&1 &" done
SSH会在提交后台命令后立即退出,不会等待服务器重启断开,既不会出现Broken pipe提示,也能让脚本自动推进到下一台服务器。
方案2:重定向输出并忽略错误
如果必须保留-t参数(比如依赖交互式sudo,但建议优先配置免密sudo),可以屏蔽所有输出并忽略SSH的非零退出状态:
for host in server1 server2; do echo "Restarting $host..." ssh -t $host "sudo reboot -f now" > /dev/null 2>&1 || true done
> /dev/null 2>&1会屏蔽包括Broken pipe在内的所有输出,|| true确保即使SSH因连接断开返回非零码,脚本也不会中断执行。
方案3:前置优化:配置免密登录与免密sudo
要彻底消除交互问题,建议先完成以下配置:
- SSH免密登录:生成密钥对,将公钥传到所有目标服务器的
~/.ssh/authorized_keys文件中,避免每次SSH连接输入密码。 - 免密sudo:在目标服务器上用
visudo编辑/etc/sudoers,添加规则(替换为你的用户名):
这样执行your_username ALL=(ALL) NOPASSWD: /sbin/rebootsudo reboot时无需输入密码,脚本全程无交互。
内容的提问来源于stack exchange,提问作者data-bite
相关产品推荐
相关产品推荐

