How to exit OpenSSH control master process without using lsof or fuser?
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.
UPDATE #1
I raised this as a potential bug to the OpenSSH upstream and they replied as follows:
Yes - this is intentional.
ControlPath may contain %-expansions that need a hostname to expand fully.
We could conceivably check to see whether ControlPath actually needs this and make the hostname optional but 1) ControlPaths that use %h are common and 2) I'd rather not make the argument parsing code more of a maze than it already is.
References
- How to tell if an ssh ControlMaster connection is in use
- How to close (kill) ssh ControlMaster connections manually