Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ssh to run a local command after connection and quit after this local command is executed?

I wish to use SSH to establish a temporary port forward, run a local command and then quit, closing the ssh connection.

The command has to be run locally, not on the remote site.

For example consider a server in a DMZ and you need to allow an application from your machine to connect to port 8080, but you have only SSH access.

How can this be done?

like image 351
sorin Avatar asked Jul 18 '12 14:07

sorin


Video Answer


2 Answers

Assuming you're using OpenSSH from the command line....

SSH can open a connection that will sustain the tunnel and remain active for as long as possible:

ssh -fNT -Llocalport:remotehost:remoteport targetserver

You can alternately have SSH launch something on the server that runs for some period of time. The tunnel will be open for that time. The SSH connection should remain after the remote command exits for as long as the tunnel is still in use. If you'll only use the tunnel once, then specify a short "sleep" to let the tunnel expire after use.

ssh -f -Llocalport:remotehost:remoteport targetserver sleep 10

If you want to be able to kill the tunnel from a script running on the local side, then I recommend you background it in your shell, then record the pid to kill later. Assuming you're using an operating system that includes Bourne shell....

#/bin/sh

ssh -f -Llocalport:remotehost:remoteport targetserver sleep 300 &
sshpid=$!
# Do your stuff within 300 seconds
kill $sshpid

If backgrounding your ssh using the shell is not to your liking, you can also use advanced ssh features to control a backgrounded process. As described here, the SSH features ControlMaster and ControlPath are how you make this work. For example, add the following to your ~/.ssh/config:

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

Now, your first connection to targetserver will set up a control, so that you can do things like this:

$ ssh -fNT -Llocalport:remoteserver:remoteport targetserver
$ ssh -O check targetserver
Master running (pid=23450)
$ <do your stuff>
$ ssh -O exit targetserver
Exit request sent.
$ ssh -O check targetserver
Control socket connect(/home/sorin/.ssh/cm_socket/[email protected]:22): No such file or directory

Obviously, these commands can be wrapped into your shell script as well.

like image 88
ghoti Avatar answered Oct 09 '22 08:10

ghoti


You could use a script similar to this (untested):

#!/bin/bash
coproc ssh -L 8080:localhost:8080 user@server
./run-local-command
echo exit >&${COPROC[1]}
wait
like image 37
dave4420 Avatar answered Oct 09 '22 09:10

dave4420