27

So I wanted to call two background ssh processes:

ssh -D localhost:8087 -fN aws-gateway-vpc1
ssh -D localhost:8088 -fN aws-gateway-vpc2

These gateways don't have the benefit of letting me set an authorized_keys file, so I must be prompted for my interactive password. That is why I'm using the -f flag and not the shell's & which will only background the process after I authenticate interactively.

In this scenario I appear to be unable to use the $! bash variable to get the pid of the recently [self] backgrounded process.

What other options do I have to find the correct pid to kill later if interrupted?

3 Answers 3

49

Finding the pid by grepping might be error prone. Alternative option would be to use ControlPath and ControlMaster options of SSH. This way you will be able to have your ssh command listen on a control socket and wait for commands from subsequent ssh calls.

Try this

ssh -D localhost:8087 -S /tmp/.ssh-aws-gateway-vpc1 -M -fN aws-gateway-vpc1
# (...)
# later, when you want to terminate ssh connection
ssh -S /tmp/.ssh-aws-gateway-vpc1 -O exit aws-gateway-vpc1

The exit command lets you kill the process without knowing the PID. If you do need the PID for anything, you can use the check command to show it:

$ ssh -S /tmp/.ssh-aws-gateway-vpc1 -O check aws-gateway-vpc1
Master running (pid=1234)
5
  • 2
    This is most reliable way to control tunnel life time if you'd asked me. Thanks indeed
    – Tagwint
    Commented Sep 12, 2019 at 14:14
  • This is a far better solution than grepping and parsing ps output. Commented Sep 17, 2019 at 22:22
  • 3
    +1, much more reliable than the ps-based solution. the "exit" command removes the need for a PID to kill the process, but I took the liberty of editing in a mention of the "check" command, which also answers the question of "how do I get the PID?" as it was initially asked.
    – Pont
    Commented Oct 3, 2019 at 9:32
  • This is fantastic. Saved me from writing PID management in bash
    – Anew
    Commented Feb 20, 2020 at 19:14
  • 1
    Okay… different from what I asked but more useable really. I like it.
    – dlamblin
    Commented Feb 11, 2021 at 2:33
9

The $! doesn't work, as you say, because it hasn't been backgrounded by the current shell. In fact, the ssh process isn't even a child of the shell you launched it from. On my Arch system, at least, it is run as a child of PID 1, the init process.

So, to get the PID, you can simply use ps:

$ ssh -f  localhost sleep 100
$ ps aux | grep '[s]sh.*-f'
terdon   20648  0.0  0.0  43308   680 ?        Ss   12:15   0:00 ssh -f localhost sleep 100

That tells me the PID is 20648*.

Alternatively, and more simply, use pgrep -f:

$ pgrep -f 'ssh.*-f'
20648

And, to kill it (them):

pkill -f 'ssh.*-f'

* See this question if you're wondering about the [s] in the grep command.

2
  • 1
    Thanks; for my purposes I used for P in ``ps -ax |grep 'ssh -D localhost:808[89] -fN'|cut -d ' ' -f 1``; do kill $P; done but not with double back-ticks, that's a md commenting thing going on here.
    – dlamblin
    Commented Aug 29, 2017 at 10:10
  • @dlamblin if that's all you want, use pkill -f 'ssh -D localhost:808[89]' (see updated answer).
    – terdon
    Commented Aug 29, 2017 at 10:13
5

I dont have 50 rep points so I have to answer... This example is not complete because you have to add multiplex control to ssh. On Debian its not enabled by default so you have to enable it via ssh_config file or even easier with "-o ControlMaster=yes" option. Try this example and it works with every ssh. It will tunnel port 3306 from example.org to your localhost on port 3307. In the example I added a port option because you also need to give it to the -O check command.

ssh -p1234 -TqfN -L 3307:localhost:3306 [email protected] -o ControlMaster=yes -o ControlPath=/dev/shm/control:%h:%p:%r -S /dev/shm/control:%h:%p:%r

Then you can use check,exit,etc. like this

ssh -p1234 -o ControlPath=/dev/shm/control:%h:%p:%r -O check [email protected]

Master running (pid=xxxx)

1
  • upvoted this answer which should be the accepted answer; the proposed solution indeed works on any system, even if ControlMaster is not enabled in ssh configuration file
    – shrike
    Commented Jun 19, 2022 at 7:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .