6

I have a bash script that creates ssh tunnel to connect remote mysql server securely as shown below.

ssh -f -N -L  $LOCAL_PORT:localhost:3306 $REMOTE_USER@$REMOTE_IP
mysql -P $LOCAL_PORT -h 127.0.0.1 -u lapl_stg -p${REMOTE_DB_PASS} < ./t1.sql > ./out.txt

After opening the ssh tunnel in the bash script, upon exit of the bash script, I noticed that the ssh tunnel child process is still alive.

After the script exits, if you do netstat, it shows below.

netstat -a -n -p -l
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name

tcp        0      0 127.0.0.1:3308          0.0.0.0:*               LISTEN      6402/ssh        
tcp        0      0 10.44.44.11:46836       10.44.44.21:22          ESTABLISHED 6402/ssh        
tcp6       0      0 ::1:3308                :::*                    LISTEN      6402/ssh   

How do you terminate the ssh child process(6402) elegantly to clean up in the script? I thought about using 'killall ssh' but it could kill other ssh processes created by others by accident.

Thank you.

user1026669
  • 143
  • 3
  • 14

1 Answers1

9

I found a way to do this using control sockets in SSH. Basically:

ssh  -M -f -N -L  $LOCAL_PORT:localhost:3306 $REMOTE_USER@$REMOTE_IP -S /tmp/ssh-control
mysql -P $LOCAL_PORT -h 127.0.0.1 -u lapl_stg -p${REMOTE_DB_PASS} < ./t1.sql > ./out.txt
ssh -S /tmp/ssh-control -O exit $REMOTE_IP

The reason why the process doesn't get killed at script exit is that -f passed to ssh forks it to the background. This is needed for SSH tunnels to work without interrupting the execution of the next line.

cwgem
  • 2,739
  • 19
  • 15
  • Thank you very much. It works. I did not know that with option -f, the ssh becomes the background process and continues running on script exit. It is hard to find this solution by just reading the ssh man page. This is much better and more elegant than 'killall ssh'. – user1026669 Mar 06 '13 at 18:22
  • If the -f option of ssh makes the ssh go into background mode, I am curious how come the 'echo $!' still does not show anything right after the ssh. – user1026669 Mar 06 '13 at 18:28
  • 1
    Well, it's *forking* into a background process, which means bash has to explicitly know to get the process ID. If you did not use `-f` and instead had `ssh -N -L $LOCAL_PORT:localhost:3306 $REMOTE_USER@$REMOTE_IP &` then the `$!` would give back a PID since you're dealing with bash job control at that point. – cwgem Mar 06 '13 at 19:02