I want to create a Linux shell (bash-) script which creates an SSH tunnel, runs a local command which uses that tunnel and finally closes the tunnel and the surrounding SSH connection.
To make this less difficult to explain consider there is a local SSH configuration to a host called 'remoteserver' containing a local private key without a password, so
ssh remoteserver -L 4444:targetserver:5555
would directly open a connection to the remote server and create a tunnel from the local port 4444 to a target server. And consider the local command would be localclient --port 4444
, how would a script look like that opens the tunnel, executes the local command and closes the tunnel after the local client application is finished?
As it should be possible to keep other parallel ongoing SSH connections, I don't want something like sudo killall ssh
.
You can try something like
The tunnel will close itself automatically after $TIMEOUT seconds. Note that using the
&
is only valid with passwordless connections. Otherwise you need to use the-f
flag of SSH.Alternatively,
will kill the tunnel just after
localclient
executes. Note that this will not work with the-f
flag because the process double forks.An
ssh
-only solution (does not work for me)The second suggestion of @damienfrancois is adquate, but for some reason I did not like the idea of having to
kill
something.Also, I could not believe
ssh
has no built-in mechanism for this. And indeed it has. This is how things should work:But for some reason, this did not work as expected for me: I first tried with something simple like
w
for theLocalCommand
but the-N
made the command hang, so I usedsleep 0
instead, which appeared to work.But when I inserted my actual network command, the result ran extremely slowly. Instead of finishing in less than one second, it took 40 seconds before even the start message appeared. I terminated the command after 20 minutes.
A pipe solution (works for me)
After some experimentation, this is what I now use:
where
keepalive.sh
on the remote side is this:The
sleep 0.5
is needed to make (sort of) sure the tunnel is set up beforelocalclient
starts (and for a far-away or slowremoteserver
, you may need a longer wait). The tunnel is terminated as soon aslocalclient
finishes because the shell terminates the pipe as soon as the second command closes its standard input.Is this better than @damienfrancois's solution? Depends.
The need for
keepalive.sh
is a clear drawback, but the way in which the tunnel is cleared away no matter how and whylocalclient
terminates is cleaner.I need this in a
Makefile
context and like the fact it fits on a single line.