1

I have a below bash shell script which I am running from machineA and that shell script will try to download a tar file from either of these two machines machineB and machineC and put it in /testing/directory1 in machineA.

And both of the machines (machineB and machineC) will have same file test.tar in the same directory /data/v1.

I need to download test.tar file from either of those two machines(machineB and machineC) from /data/v1 directory. If machineB is up, then I will download the tar file from machineB and if it is down, then I will download the same tar file from machineC..

But currently in my bash shell script suppose for whatever reason if machineB is down, then I guess it won't even try to download the same tar file from machineC and it will throw an exception and stop the shell script.

I want to use set -e but it should throw an exception only when both of the machines are down and not able to download the tar file from machineB and machineC. If machineB is down for whatever reason, then it should try downloading from machineC..

#!/bin/bash
set -e

readonly PATH_LOCATION=/testing/directory1
readonly MACHINES=(machineB machineC)
readonly FILE_LOCATION=/data/v1
readonly FILE_NAME=test.tar

length1=$(ssh -o "StrictHostKeyChecking no" david@${MACHINES[0]} "ls '$FILE_LOCATION' | wc -l")
length2=$(ssh -o "StrictHostKeyChecking no" david@${MACHINES[1]} "ls '$FILE_LOCATION' | wc -l")

echo $length1
echo $length2

if [ "$length1" -gt 0 ] || [ "$length2" -gt 0 ]
then
    rm -rf $PATH_LOCATION/*
    scp david@${MACHINES[0]}:$FILE_LOCATION/$FILE_NAME $PATH_LOCATION/. || scp david@${MACHINES[1]}:$FILE_LOCATION/$FILE_NAME $PATH_LOCATION/.
    tar -xvf $PATH_LOCATION/$FILE_NAME -C $PATH_LOCATION
    rm $PATH_LOCATION/$FILE_NAME
fi

Any thoughts how this can be done? I want to use scp only here not rsync as I need to spend some time understanding rsync.

3

You are needlessly complicating things. Just try machineA and if that fails, go to machineB:

#!/usr/bin/env bash
set -e

readonly PATH_LOCATION=/testing/directory1
readonly MACHINES=(machineB machineC)
readonly FILE_LOCATION=/data/v1
readonly FILE_NAME=test.tar
readonly TARGET="$FILE_LOCATION/$FILE_NAME"


for MACHINE in ${MACHINES[@]}; do
    scp david@$MACHINE:$TARGET $PATH_LOCATION && break
done

If you want to know which host you downloaded from, you could do:

for MACHINE in ${MACHINES[@]}; do
    if scp david@$MACHINE:$TARGET $PATH_LOCATION; then
      echo "Downloaded from $MACHINE";
      break;
    fi
done

And if you want to do something else if neither machine is up:

for MACHINE in ${MACHINES[@]}; do
    if scp david@$MACHINE:$TARGET $PATH_LOCATION; then
      echo "Downloaded from $MACHINE";
      break;
    fi
done
if [[ $? -eq 1 ]]; then
   echo "Download failed"
fi
2
  • Thanks terdon. What will happen if machineB also fails, then it will throw an exception because of set -e? – arsenal Jan 26 '14 at 20:12
  • @Webby The return code will be whatever was returned by the last scp attempted so it will be 1 if both machones are down. See updated answer for how to do something if that happens. Also note that this does not check if the machine is up so it will also return the same error if it is up but the remote file does not exist for example. – terdon Jan 26 '14 at 20:26
2
if ping -c 3 -W 1 hostA >/dev/null; then
 SRV=hostA
elif ping -c 3 -W1 hostB >/dev/null; then
 SRV=hostB
else
 echo "cannot contact either hostA or hostB"
 exit 1
fi

scp david@$SRV:$FILE_LOCATION/$FILE_NAME $PATH_LOCATION/. 
RET=$?

echo "Return code is $RET"

...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.