How to tell if an ssh ControlMaster connection is in use
Solution 1
You could simply use
ssh -o ControlPath=$socket -O check
for each $socket you've open (easy if you keep them in a single directory).
This returns 255 if the check fails (connection not active anymore), an other value if it pass. You may need to specify the hostname too, but nothing that an awk on $socket won't give you :)
Solution 2
@Renik's answer didn't work for me. See below for what did.
This works for me using just the socket file for the control master:
$ ssh -o ControlPath=~/.ssh/<controlfile> -O check <bogus arg>
NOTE: You can also use ssh -S ~/.ssh/<controlfile> ...
as well, which is a bit shorter form of the above.
Example
Here's an example where I've already established a connection to a remote server:
$ ssh -S ~/.ssh/master-57db26a0499dfd881986e23a2e4dd5c5c63e26c2 -O check blah
Master running (pid=89228)
$
And with it disconnected:
$ ssh -S ~/.ssh/master-66496a62823573e4760469df70e57ce4c15afd74 -O check blah
Control socket connect(/Users/user1/.ssh/master-66496a62823573e4760469df70e57ce4c15afd74): No such file or directory
$
If it were still connected, this would force it to exit immediately:
$ ssh -S ~/.ssh/master-66496a62823573e4760469df70e57ce4c15afd74 -O exit blah
Exit request sent.
$
It's unclear to me, but it would appear to potentially be a bug in ssh
that it requires an additional argument at the end, even though blah
is meaningless in the context of the switches I'm using.
Without it gives me this:
$ 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]
Version info
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
I confirmed that on both of these versions, the need for the additional bogus argument was required.
References
- How to close (kill) ssh ControlMaster connections manually
- How to exit OpenSSH control master process without using lsof or fuser?
Solution 3
I wrote a utility that eases management of SSH ControlMaster connections. It's called cmc
:
TimidRobot/cmc: ControlMaster Controller - Eases management of SSH ControlMaster connections.
Related videos on Youtube
Comments
-
user1871402 almost 2 years
I'd like to use
ssh
's ControlMaster feature to share connections for speed increases. I'm trying to script it so that I can start/restart/stop a number of connections to different hosts.How can I determine whether any of these connections are in use? If I kill them when an ssh session is open, it gets closed
My restart script would ideally look like (pseudo-script) - the stop script would be equivalent without the ssh command at the bottom:
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
-
user1871402 over 13 yearsThat's much simpler for seeing if the existing connection is open; it doesn't tell me if it is actually being used, but I guess that isn't so important... (and I have the method below)
-
Dan Lenski over 2 yearsThe problem with this is it will hang forever in some cases, even with
ConnectTimeout
options. For example, if I have a control socket "open" tosome_host
over a network route that no longer exists,ssh -o ConnectTimeout=5 -O check some_host
hangs forever. OpenSSH itself appears to have no way to detect/recover from this: I have to usetimeout 5 ssh -O check some_host
.