-   Programming (
-   -   bash script suggestions for waiting for ssh -L (

iggymac 03-20-2005 10:37 PM

bash script suggestions for waiting for ssh -L
I need to write a bash script that checks to see if "ssh -L" (forwarding a local port to my backup server) is running; if it isn't, start it, if it is, run the rsync backup, then kill the tunnel.

There are a few problems I don't know how to overcome, though:

1. ssh -L takes a little while to come up sometimes, so the backup has to check the status of the ssh -L command before running, of course.

2. I can't run the ssh -L command more than once, because if I do, it creates multiple tunnels.

3. The ssh -L command doesn't let go of the shell, so I have to stick in a &, which seems like a kludge to me.

I'm a beginner in shell scripting, so my current script is pretty sad, and certain parts don't work yet. Here it is (don't laugh too hard):


if [ -z $(ps -elf | grep 'ssh -L' | grep -v grep | awk '{print $4}') ]
echo "ssh tunnel is down..."
echo "Bringing up ssh tunnel..."
/usr/bin/ssh -L 873:X.X.X.X:873 -l admin -N X.X.X.X &
echo "ssh tunnel is up"

until [ -n $(ps -elf | grep 'ssh -L' | grep -v grep | awk '{print $4}') ]
echo "waiting for tunnel..."

if [ -n $(ps -elf | grep 'ssh -L' | grep -v grep | awk '{print $4}') ]
echo "Starting backup..."
/usr/local/bin/rsync blah blah blah...

if [ -z $(ps -elf | grep 'ssh -L' | grep -v grep | awk '{print $4}') ]
echo "The tunnel may have disconnected during backup.
kill `ps -elf | grep 'ssh -L' | grep -v grep | awk '{print $4}'`
echo "Backup completed."

So, first of all, ny "until" command doesn't seem to work at all.
Second, I'm obviously calling for the same info (the pid) many times, and I assume there is a simpler way.

Any suggestions on what would be simpler and better?


dustu76 03-21-2005 01:19 AM

I have no idea of ssh/rsync (I hope rsync/ssh do return proper return codes), but still...:


sshcmd='ssh -L 873:X.X.X.X:873 -l admin -N X.X.X.X'
backupcmd='/usr/local/bin/rsync blah blah blah'
grepstring='ssh -L'

        ## Kill -0 would return true if the said pid exists
        ## else the process has died or was killed
        if kill -0 $progpid 2>/dev/null
                echo "Program running in background : Pid = $progpid"
                return 0
                echo "Problem : Program could not be started"
                return 1

## Save pid of any process whose command line matches "ssh -L"
sshpid=$(ps -elf | grep "${grepstring}" | grep -v grep | awk '{print $4}')

## If sshpid is null then there is no process matching "ssh -L"
## Else we have the pid of the process.
if [ "${sshpid}x" = "x" ] ; then
        echo "Bringing up : $sshcmd"
        $sshcmd &

        check_pid "${sshpid}"
        [ $? -ne 0 ] && exit 2
        echo "Already up : $sshcmd [Pid : $sshpid]"

## If we reach this stage, we have the ssh tunnel ready
## so we can proceed
echo "Starting backup : $backupcmd"
$backupcmd &            # Fire the backup process in background
bkpid=$!                    # This gives the pid of the background backup process

# Check whether the pid returned still exists
# This is becuase even if you fire an invalid command in background
# you would return the pid BUT it would be gone since ... well, it was invalid!
# So you need check once more.
check_pid "${bkpid}"   
[ $? -ne 0 ] && exit 2  # If not then no point continuing.

# IF we reach this stage, backup process was successfully running in background
echo "Waiting for backup to get over"
wait $bkpid                # wait command waits for the completion of the given pid
backupstatus=$?        # and $? would contain the completion status of the comand

        if [ $backupstatus -eq 0 ] ; then
                echo "Backup completed successfully"
                echo "Backup may have some problem : return code = $backupstatus"

echo "Cleaning up ssh tunnel"
kill -TERM $sshpid

You can modify this to suit your needs. If you have any doubts (or you spot some goofup!!!), please let me know.


Edit : I have corrected the check_pid function and added some comments. Glad to be of help.

iggymac 03-21-2005 12:22 PM

Wow. Thanks very much. You didn't need to write the whole thing for me :) .

You're a little over my head, though, with some of this script. If you have the time, could you run some basic comments about what this is doing?

If not, that's ok. I will do some more reading and try to break it down.



TheLinuxDuck 03-22-2005 08:59 AM


Without having even glanced at the script posted by dustu76, I'll offer you a link instead. Check out Sub Shells and more importantly, look at example 20-3 at the bottom of the page. It shows an example of executing commands into it's own process, and then having the master script wait for the subs to finish. I think that this would serve your purposes nicely. Plus, it's a chance to learn something new. (=

Happy bashing!

iggymac 03-22-2005 08:04 PM

Thanks for the link. I'll check it out as soon as I can. I have read portions of the Advanced Bash-Scripting Guide - I guess I should read the whole thing. :)

Thanks again to you and dustu76. I think I can take it from here (and I've already learned a few things!).


All times are GMT -5. The time now is 03:09 PM.