我想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 连接的管理。它叫做cmc
:
TimidRobot/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
因此sed
和cut
)
搜索子进程更加棘手。主进程为每个子进程打开一个新套接字,连接到标准文件。子进程包含一个简单标记为 的套接字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
}