如何判断 ssh ControlMaster 连接是否正在使用

如何判断 ssh ControlMaster 连接是否正在使用

我想ssh使用控制大师共享连接以提高速度的功能。我正在尝试编写脚本,以便可以启动/重新启动/停止与不同主机的多个连接。

我如何确定这些连接是否正在使用?如果我在 ssh 会话打开时终止它们,则会话将关闭。

我的重启脚本理想情况下应该是这样的(伪脚本)——停止脚本在底部没有 ssh 命令的情况下是等效的:

for HOST in $HOST_LIST
  do
    MASTER_PID=`find_master_pid $HOST`
    if $MASTER_PID
      then
        if `find_child_pid`
          echo Connection to $HOST in use: not terminating
        else
          kill -SIGHUP $MASTER_PID
        fi
    ssh -TMNf $HOST

答案1

你可以简单地使用

ssh -o ControlPath=$socket -O check 'unused-hostname'

对于您打开的每个 $socket (如果您将它们保存在一个目录中,则很容易)。

如果检查失败(连接不再处于活动状态),则返回 255;如果检查通过,则返回其他值。您可能还需要指定主机名,但 $socket 上的 awk 不会给您提供任何信息 :)

答案2

@Renik 的答案对我不起作用。请参阅下文了解解决方法。


对于我来说,这仅使用控制主机的套接字文件即可:

$ ssh -o ControlPath=~/.ssh/<controlfile> -O check <bogus arg>

笔记:您还可以使用ssh -S ~/.ssh/<controlfile> ...as well,这是上述形式的稍短形式。

例子

下面是我已经与远程服务器建立连接的示例:

$ ssh -S ~/.ssh/master-57db26a0499dfd881986e23a2e4dd5c5c63e26c2 -O check blah
Master running (pid=89228)
$

并将其断开:

$ ssh -S ~/.ssh/master-66496a62823573e4760469df70e57ce4c15afd74 -O check blah
Control socket connect(/Users/user1/.ssh/master-66496a62823573e4760469df70e57ce4c15afd74): No such file or directory
$

如果它仍然连接,这将强制它立即退出:

$ ssh -S ~/.ssh/master-66496a62823573e4760469df70e57ce4c15afd74 -O exit blah
Exit request sent.
$

我不清楚,但它似乎可能是一个错误,因为ssh 它需要在最后添加一个额外的参数,即使blah在我使用的开关上下文中毫无意义。

如果没有它,我会得到这个:

$ ssh -S ~/.ssh/master-57db26a0499dfd881986e23a2e4dd5c5c63e26c2 -O check
usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
           [-D [bind_address:]port] [-E log_file] [-e escape_char]
           [-F configfile] [-I pkcs11] [-i identity_file]
           [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]
           [-O ctl_cmd] [-o option] [-p port]
           [-Q cipher | cipher-auth | mac | kex | key]
           [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]
           [-w local_tun[:remote_tun]] [user@]hostname [command]

版本信息

OSX
$ ssh -V
OpenSSH_6.9p1, LibreSSL 2.1.8
CentOS 7.x
$ ssh -V
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017

我确认这两个版本都需要额外的虚假论点。

参考

答案3

我编写了一个实用程序,可以简化 SSH ControlMaster 连接的管理。它叫做cmcTimidRobot/cmc:ControlMaster 控制器 - 简化 SSH ControlMaster 连接的管理

答案4

我目前的方法是使用lsof来查找 Unix 套接字。如果我知道指定的目标文件名,ControlPath我可以像这样搜索主进程:

function find_master_pid() {
  lsof -a -U -u $USER -c ssh | grep $CM_DIR/$RUSER@$HOST | sed 's/^ssh *//' | cut -d' ' -f1 | sort -u
}

然后这将给我PID(不幸的是,直接将 unix 套接字文件的文件名提供给lsof不起作用,否则我可以只要求它输出带有pid;-f因此sedcut

搜索子进程更加棘手。主进程为每个子进程打开一个新套接字,连接到标准文件。子进程包含一个简单标记为 的套接字socket。但是, 返回的 inodelsof比相应的主进程套接字小一。因此,以下查找连接到主进程的子进程(这需要$MASTER_PID进行检查)

function find_child_pid() {
  for CHILD_PID in `lsof -a -U -u $USER -c ssh | grep socket | sed 's/^ssh *//' | cut -d' ' -f1 | sort -u`
    do
      CHECK_PID=0
      for NODE in `lsof -a -U -u $USER -p $CHILD_PID -F i | grep ^i | sed 's/i//'`
        do
          MASTER_NODE=$((NODE+1))
          CHECK_PID=`lsof -a -U -u $USER -p $MASTER_PID | grep $MASTER_NODE | wc -l`
          [[ $CHECK_PID == 1 ]] && echo $CHILD_PID
        done
    done
}

相关内容