Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I kill a backgrounded/detached ssh session?

I am using the program synergy together with an ssh tunnel

It works, i just have to open an console an type these two commands:

ssh -f -N -L localhost:12345:otherHost:12345 otherUser@OtherHost
synergyc localhost

because im lazy i made an Bash-Script which is run with one mouseclick on an icon:

#!/bin/bash
ssh -f -N -L localhost:12345:otherHost:12345 otherUser@OtherHost
synergyc localhost

the Bash-Script above works as well, but now i also want to kill synergy and the ssh tunnel via one mouseclick, so i have to save the PIDs of synergy and ssh into file to kill them later:

#!/bin/bash

mkdir -p /tmp/synergyPIDs || exit 1
rm -f /tmp/synergyPIDs/ssh || exit 1
rm -f /tmp/synergyPIDs/synergy || exit 1

[ ! -e /tmp/synergyPIDs/ssh ] || exit 1
[ ! -e /tmp/synergyPIDs/synergy ] || exit 1

ssh -f -N -L localhost:12345:otherHost:12345 otherUser@OtherHost
echo $! > /tmp/synergyPIDs/ssh
synergyc localhost
echo $! > /tmp/synergyPIDs/synergy

But the files of this script are empty.

How do I get the PIDs of ssh and synergy?
(I try to avoid ps aux | grep ... | awk ... | sed ... combinations, there has to be an easier way.)

like image 472
Skaarj Avatar asked Nov 30 '09 19:11

Skaarj


People also ask

How do I kill an unresponsive ssh session?

macOS, Linux / UNIX kill unresponsive hung SSH session So all you've to do is press Enter key followed by ~. (tilde, period). Please note that escapes are only recognized immediately after newline.

How do I force close an ssh session?

In that case, you can type ~. to close the SSH session and return to your local command line terminal. This works as an escape character for SSH connections.

How do I stop ssh tunneling?

To kill the tunnel, use ps -C ssh or ps | grep ssh or any other variant to determine which ssh process is running your tunnel. Then kill it. If you want to kill all ssh clients running on your machine (as your user), pkill ssh will do it.

Does close A ssh session without killing process?

ssh into your remote box. type screen Then start the process you want. Press Ctrl-A then Ctrl-D. This will detach your screen session but leave your processes running.


4 Answers

With all due respect to the users of pgrep, pkill, ps | awk, etc, there is a much better way.

Consider that if you rely on ps -aux | grep ... to find a process you run the risk of a collision. You may have a use case where that is unlikely, but as a general rule, it's not the way to go.

SSH provides a mechanism for managing and controlling background processes. But like so many SSH things, it's an "advanced" feature, and many people (it seems, from the other answers here) are unaware of its existence.

In my own use case, I have a workstation at home on which I want to leave a tunnel that connects to an HTTP proxy on the internal network at my office, and another one that gives me quick access to management interfaces on co-located servers. This is how you might create the basic tunnels, initiated from home:

$ ssh -fNT -L8888:proxyhost:8888 -R22222:localhost:22 officefirewall
$ ssh -fNT -L4431:www1:443 -L4432:www2:443 colocatedserver

These cause ssh to background itself, leaving the tunnels open. But if the tunnel goes away, I'm stuck, and if I want to find it, I have to parse my process list and home I've got the "right" ssh (in case I've accidentally launched multiple ones that look similar).

Instead, if I want to manage multiple connections, I use SSH's ControlMaster config option, along with the -O command-line option for control. For example, with the following in my ~/.ssh/config file,

host officefirewall colocatedserver
    ControlMaster auto
    ControlPath ~/.ssh/cm_sockets/%r@%h:%p

the ssh commands above, when run, will leave spoor in ~/.ssh/cm_sockets/ which can then provide access for control, for example:

$ ssh -O check officefirewall
Master running (pid=23980)
$ ssh -O exit officefirewall
Exit request sent.
$ ssh -O check officefirewall
Control socket connect(/home/ghoti/.ssh/cm_socket/[email protected]:22): No such file or directory

And at this point, the tunnel (and controlling SSH session) is gone, without the need to use a hammer (kill, killall, pkill, etc).

Bringing this back to your use-case...

You're establishing the tunnel through which you want syngergyc to talk to syngergys on TCP port 12345. For that, I'd do something like the following.

Add an entry to your ~/.ssh/config file:

Host otherHosttunnel
    HostName otherHost
    User otherUser
    LocalForward 12345 otherHost:12345
    RequestTTY no
    ExitOnForwardFailure yes
    ControlMaster auto
    ControlPath ~/.ssh/cm_sockets/%r@%h:%p

Note that the command line -L option is handled with the LocalForward keyword, and the Control{Master,Path} lines are included to make sure you have control after the tunnel is established.

Then, you might modify your bash script to something like this:

#!/bin/bash

if ! ssh -f -N otherHosttunnel; then
    echo "ERROR: couldn't start tunnel." >&2
    exit 1
else
    synergyc localhost
    ssh -O exit otherHosttunnel
fi

The -f option backgrounds the tunnel, leaving a socket on your ControlPath to close the tunnel later. If the ssh fails (which it might due to a network error or ExitOnForwardFailure), there's no need to exit the tunnel, but if it did not fail (else), synergyc is launched and then the tunnel is closed after it exits.

You might also want to look in to whether the SSH option LocalCommand could be used to launch synergyc from right within your ssh config file.

like image 155
ghoti Avatar answered Oct 20 '22 14:10

ghoti


Quick summary: Will not work.

My first idea is that you need to start the processes in the background to get their PIDs with $!.

A pattern like

some_program &
some_pid=$!
wait $some_pid

might do what you need... except that then ssh won't be in the foreground to ask for passphrases any more.

Well then, you might need something different after all. ssh -f probably spawns a new process your shell can never know from invoking it anyway. Ideally, ssh itself would offer a way to write its PID into some file.

like image 23
ndim Avatar answered Oct 20 '22 16:10

ndim


just came across this thread and wanted to mention the "pidof" linux utility:

$ pidof init
1
like image 21
zrathen Avatar answered Oct 20 '22 14:10

zrathen


You can use lsof to show the pid of the process listening to port 12345 on localhost:

lsof -t -i @localhost:12345 -sTCP:listen

Examples:

PID=$(lsof -t -i @localhost:12345 -sTCP:listen)
lsof -t -i @localhost:12345 -sTCP:listen >/dev/null && echo "Port in use"
like image 16
Atle Avatar answered Oct 20 '22 15:10

Atle