LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   bash script suggestions for waiting for ssh -L (http://www.linuxquestions.org/questions/programming-9/bash-script-suggestions-for-waiting-for-ssh-l-304103/)

iggymac 03-20-2005 09: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):

#!/bin/bash

if [ -z $(ps -elf | grep 'ssh -L' | grep -v grep | awk '{print $4}') ]
then
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 &
else
echo "ssh tunnel is up"
fi

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

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

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


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?

Bret

dustu76 03-21-2005 12:19 AM

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

Code:

#!/bin/bash
#-----------------------------------------------------------------------
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'

#-----------------------------------------------------------------------
check_pid()
{
        progpid=$1
        ## 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
        then
                echo "Program running in background : Pid = $progpid"
                return 0
        else
                echo "Problem : Program could not be started"
                return 1
        fi
}

#-----------------------------------------------------------------------
## 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 &
        sshpid=$!

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

#-----------------------------------------------------------------------
## 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"
        else
                echo "Backup may have some problem : return code = $backupstatus"
        fi

#-----------------------------------------------------------------------
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.

HTH


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

iggymac 03-21-2005 11:22 AM

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.

Thanks!

Bret

TheLinuxDuck 03-22-2005 07:59 AM

iggymac:

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 07: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!).

Bret


All times are GMT -5. The time now is 01:52 PM.