我正在尝试监视远程 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
天。”。