ssh 远程命令因连接丢失而挂起

ssh 远程命令因连接丢失而挂起

我正在尝试监视远程 PC 上服务的执行情况并根据结果执行功能。所以这个函数应该是这样的:

  • 如果服务“X”正在系统 1 上运行,则在系统 2 上不执行任何操作
  • 如果服务“X”是没有运行在系统 1 上,启动系统 2 上的服务“Y”

因此我想这样pgrep使用:ssh

ssh [email protected] pgrep -x "service"

如果在执行上述命令行期间两个系统之间的连接被切断,我的脚本就会卡住。如果连接在执行之前被切断,则会失败并出现预期的错误。

执行 ssh 并-o ConnectTimeout=1没有解决问题,因为 SSH 连接是在连接被切断时建立的。

我预计连接最终会断开并进一步执行我的脚本。但即使几分钟后,脚本也会挂起在这个远程执行的命令上。

答案1

有两个 ssh 配置选项旨在帮助 ssh 客户端检测与远程计算机上的 ssh 服务器的断开连接。他们是-o ServerAliveInterval=15-o ServerAliveCountMax=3。间隔是客户端向服务器(远程计算机)请求答复的探测之间的秒数,而最大计数是客户端确定连接已断开的连续失败次数。

客户端检测问题并结束会话(向脚本返回错误代码)需要大约 45 秒的时间。如果将最大计数设置为 0(默认值),则不会发送探测器来检测问题,并且可能需要 10 分钟或更长时间。

在我看来,将组合设置为少于 45 秒会增加 ssh 客户端过早断开连接的风险,并在网络缓慢而不是连接中断时中断监控。将间隔设置为超过 60-120 秒会存在这样的风险:防火墙等网络设备会断开空闲而不是断开的连接(并中断您的连接)。

(我没有讨论该TCPKeepAlive选项,因为它对于检测断开的连接或保持连接活动不如ServerAlive*选项那么有用)

答案2

您可以使用该timeout命令将其包装ssh在时间有限的上下文中

pid=$(timeout 10s ssh -n [email protected] 'pgrep -x service' 2>/dev/null)
ss=$?

case "$ss" in
    124)    echo "Timeout" >&2 ;;
    1[23?)  echo "Something went badly wrong ($ss)" >&2 ;;
    0)      echo "All is well" >&2 ;;
    *)      echo "An error occurred with the remote execution ($ss)" >&2 ;;
esac

if [ -z "$pid" ]
then
    echo "No result from ssh pgrep" >&2
fi

文档 ( man timeout) 将持续时间定义为“带有可选后缀的浮点数:s秒(默认)、m分钟、h小时或d天。”。

相关内容