Shell 如何在多台机器上批量运行许多SSH远程命令?

Shell 如何在多台机器上批量运行许多SSH远程命令?,shell,for-loop,ssh,timeout,Shell,For Loop,Ssh,Timeout,我使用SSH在for循环中的多个远程机器上运行一些命令。它对IP地址列表执行相同的命令。有些IP地址可能无法访问,因此我使用了ConnectTimeout选项 然而,我的脚本并没有按照我想要的方式工作。实际上,它在第一个无法访问的IP上卡住了,而不是放弃并尝试我列表上的下一个IP地址 以下是我脚本的相关部分: for ip in ${IP} ; do ssh -o BatchMode=yes \ -o StrictHostKeyChecking=no \

我使用SSH在
for
循环中的多个远程机器上运行一些命令。它对IP地址列表执行相同的命令。有些IP地址可能无法访问,因此我使用了
ConnectTimeout
选项

然而,我的脚本并没有按照我想要的方式工作。实际上,它在第一个无法访问的IP上卡住了,而不是放弃并尝试我列表上的下一个IP地址

以下是我脚本的相关部分:

for ip in ${IP} ; do
    ssh  -o BatchMode=yes \
         -o StrictHostKeyChecking=no \
         -o ConnectTimeout=10 \
         -l ${USERNAME} \
         ${SCRIPT_HOST} \
         "${COMMAND} -i $ip || echo timeout" \
         >> ./myscript.out
done
对于可访问的IP,它工作正常,但如果某个特定IP关闭,它会等待一段时间(远远超过10秒,可能35-40秒),并向我的终端显示一条错误消息:

连接错误:连接超时


所以我想知道我没有正确使用哪个选项。

您使用的
ConnectTimeout
是正确的,所以不清楚为什么它只在30秒或更长时间后超时

下面是我如何更改您的脚本以完全避免超时问题:

  • 使用GNU
    parallel
    可同时连接到多个目标主机
  • 使用SSH的
    -f
    选项在后台处理它
下面是一个GNU并行的解决方案,同时最多运行50个连接:

parallel --gnu --bg --jobs 50 \
ssh -o BatchMode=yes \
    -o StrictHostKeyChecking=no \
    -o ConnectTimeout=10 \
    -l ${USERNAME} \
    {} \
    "${COMMAND} -i {} || echo timeout" \
::: ${IP}
parallel::
将通过拆分
列表并行执行多次
的占位符是
{}


使用
parallel--jobs n
来限制并行连接的数量。

连接超时适用于您已经建立连接的情况,如果连接在以秒为单位的时间内保持空闲,则它将断开连接(也就是说,如果您没有激活KEEP_ALIVE ssh参数来防止连接处于空闲状态)


超时需要30秒以上的时间,原因是TCP协议内部计时器尝试连接该时间段,并返回错误消息,表示无法连接到sftp服务器。它不是来自ssh。

它不能在后台运行吗?通过执行
2>/dev/null
忽略错误,对吗ried在调试模式(即详细模式)下执行ssh?这个答案与ssh文档相矛盾(而且,即使操作系统不允许您缩短套接字上的超时时间,您仍然可以运行自己的计时器,并在任何时候停止尝试)。以下是
ssh\u配置(5)中的相关部分
关于
ConnectTimeout
选项的手册页面:“指定连接到SSH服务器时使用的超时(以秒为单位),而不是使用默认的系统TCP超时。此值仅在目标关闭或确实无法访问时使用,而不是在目标拒绝连接时使用。”