How to tell if an ssh ControlMaster connection is in use

6,395

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

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.

Share:
6,395

Related videos on Youtube

user1871402
Author by

user1871402

I'm me

Updated on September 17, 2022

Comments

  • user1871402
    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
    user1871402 over 13 years
    That'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
    Dan Lenski over 2 years
    The problem with this is it will hang forever in some cases, even with ConnectTimeout options. For example, if I have a control socket "open" to some_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 use timeout 5 ssh -O check some_host.