简体   繁体   English

Shell脚本循环遍历文件,ssh进入远程服务器并且复制文件继续失败

[英]Shell script loop through file, ssh into remote server and copy files continue on fail

Given the following file, I cannot figure out how to continue to iterate through the lines one by one without it exiting on first failure of the inner most remote ssh command. 鉴于以下文件,我无法弄清楚如何继续迭代遍历这些行,而不会在内部最远的ssh命令的第一次失败时退出。

The basic premise is this script ssh's to a remote server defined as INPUT_FILE as USER and copies a bunch of files off to a remote location for backup.. the actual backup script is in backup.sh . 基本前提是这个脚本ssh到一个定义为INPUT_FILE的远程服务器作为USER并将一堆文件复制到远程位置进行备份..实际的备份脚本在backup.sh which controller.sh executes. 哪个controller.sh执行。

My problem is that if the backup.sh throws an error, something like a permission denied for cp the whole while loop finishs and it won't connect to any of the remaing servers in my INPUT_FILE . 我的问题是,如果backup.sh抛出一个错误,就像cp的权限被拒绝整个while循环结束,它将不会连接到我的INPUT_FILE任何重INPUT_FILE服务器。 I know this because I have purposely put in place permissions on various servers to test this scenario. 我知道这是因为我故意在各种服务器上设置权限来测试这种情况。

How can i iterate through the files, and wait for the first ssh command to complete and force it to go to the next line without exiting. 我如何遍历文件,等待第一个ssh命令完成并强制它转到下一行而不退出。

controller.sh controller.sh

INPUT_FILE=$1
USER=$2
SCRIPT_DIR=/opt/sapdownloads/MikesUtilities/backups
BACKUP_DIR=$SCRIPT_DIR/data
DATE=`date +%m%d%y`
LOG_FILE=$SCRIPT_DIR/logs/backup.controller.log


##
# Create The Log dir and log files
##
function log(){
   echo -e ${*}
   echo -e "[${USER}][`date`] - ${*}" >> ${LOG_FILE}
}


#Iterate through the input file line by line

cat $INPUT_FILE | while read l;do {
   #Split the line by spaces into an array
   line=($l)
   #make sure server is lower case
   SERVER=`echo ${line[1]} | tr [:lower:] [:upper:]`
   #make sure tier is uppercase
   TIER=`echo ${line[0]} | tr [:upper:] [:lower:]`
   log "###################################"
   log "#  Tier: $TIER | SERVER: $SERVER  #"
   log "###################################"
   log "Making Sure we can login to the Server"
   CHK=`ssh -t -q -o "BatchMode yes" -o "ConnectTimeout 5" -l $USER $SERVER "echo success"`;
   if [ "success" = $CHK ] >/dev/null 2>&1
   then
      CPDIR=$BACKUP_DIR/$TIER/$SERVER/$DATE
      log "Creating new backup directories in $CPDIR"
      #make the new backup directory in $BACKUP_DIR
      mkdir -p $BACKUP_DIR/$TIER/$SERVER/$DATE/etc
      mkdir -p $BACKUP_DIR/$TIER/$SERVER/$DATE/home


      log "Executing Remote Backup Script"
      ret=`ssh -n -t -q -o "BatchMode yes" -o "ConnectTimeout 5" -l $USER $SERVER "/bin/bash $SCRIPT_DIR/backup.sh $CPDIR; echo $?"`
      echo "return: [$ret]"
      if [ $ret -eq 0 ]; then
         echo "Success. Aborting"
         break
      fi
   else
      printf "${i}\tUnable to connect to host\n" >> $ERRORS;
   fi
} </dev/null; done

backup.sh backup.sh

#!/bin/bash
CPDIR=$1
DATE=`date +%m%d%y`
SCRIPT_DIR=/opt/sapdownloads/MikesUtilities/backups
LOG_FILE=$SCRIPT_DIR/logs/backup.log
SIDADM_HOME=/home/${sapsid}adm
ORASID_HOME=/home/ora${sapsid}
ORACLE_HOME=/home/oracle
cpErrors=()
message=""
SENDTO="joe@example.com"
SENDFROM="team@example.com"

##
# Create The Log dir and log files
##
function log(){
   #echo -e ${*}
   echo -e "[${USER}][`date`] - ${*}" >> ${LOG_FILE}
}

function compileMessage(){
   message="Unable to CP one or more files from the server $HOSTNAME \n\n"
   for i in "${cpErrors[@]}"
   do
      message+="${i}\n"
   done
}

function sendMail(){
   compileMessage

   echo -e $message | mail -s "OS Backup Errors" -r $SENDFROM $SENDTO
}

cd /etc
#copy fstab
if [ -d "oratab" ]; then
   log "Copying oratab to $CPDIR/etc"
   cp oratab $CPDIR/etc
fi
#Copy fstab
if [ -d "fstab" ]; then
   log "Copying fstab to $CPDIR/etc"
   cp fstab $CPDIR/etc
fi

#make sure that folder exists first
if [ -d "$ORASID_HOME" ]; then

   #Test to make sure we can access the folder
   if [ -w "$ORASID_HOME" ]; then
      log "Copying $ORASID_HOME to $CPDIR/home"
      cp -rf $ORASID_HOME $CPDIR/home
   else
      #if we cant access that folder, send an email
      log "Unable to cp $ORASID_HOME to $CPDIR/home"
      cpErrors+=($ORASID_HOME)
   fi

fi

#make sure that folder exists first
if [ -d "$SIDADM_HOME" ]; then

   #Test to make sure we can access the folder
   if [ -w "$SIDADM_HOME" ]; then
      log "Copying $SIDADM_HOME to $CPDIR/home"
      cp -rf $SIDADM_HOME $CPDIR/home
   else
      #if we cant access that folder, send an email
      log "Unable to cp $SIDADM_HOME to $CPDIR/home"
      cpErrors+=($SIDADM_HOME)
   fi

fi

#make sure that folder exists first
if [ -d "$ORACLE_HOME" ]; then

   #Test to make sure we can access the folder
   if [ -w "$ORACLE_HOME" ]; then
      log "Copying $ORACLE_HOME to $CPDIR/home"
      cp -rf $ORACLE_HOME $CPDIR/home
   else
      #if we cant access that folder, send an email
      log "Unable to cp $ORACLE_HOME to $CPDIR/home"
      cpErrors+=($ORACLE_HOME)
   fi

fi


if [ ${#cpErrors[@]} != 0 ]; then
   log "Sending Email of cp errors"
   sendMail
fi

As you probably have guessed, ssh is eating your input from the while loop, and that's why it's failing. 正如您可能已经猜到的那样, ssh正在从while循环中获取您的输入,这就是它失败的原因。 Actually I'm not 100% sure why -n is not working in this case, but we can work around it. 实际上我并不是100%肯定为什么-n在这种情况下不起作用,但我们可以解决它。

Since I don't have your backup scripts (nor the general setup), I simplified the script quite a bit, but I think the general idea is same. 由于我没有备份脚本(也没有常规设置),所以我简化了脚本,但我认为总体思路是一样的。 Go through input file that server information, and try to find a server we can login to, and then see if we can successfully execute a script there 通过输入文件获取服务器信息,并尝试找到我们可以登录的服务器,然后看看我们是否可以在那里成功执行脚本

I call a simple script on a remote machine that waited for couple of seconds, and returned an exit code . 我在一台等待几秒钟的远程机器上调用一个简单的脚本,并返回exit code You should add some exit codes to your Backup.sh , so that you can check what was returned from the remote command, and then act on it. 您应该向Backup.sh添加一些退出代码,以便您可以检查从远程命令返回的内容,然后对其进行操作。

So with adding curly braces to the while (and </dev/null ), and retrieve exit code from your remote script, I was able to go through the list until a successful remote script execution was done: 因此,通过向while(和</dev/null )添加花括号 ,并从远程脚本中检索退出代码 ,我可以浏览列表,直到成功完成远程脚本执行:

cat $INPUT_FILE | while read l;do {

SERVER=($l)
CHK=`ssh -t -q -o "BatchMode yes" -o "ConnectTimeout 5" -l $USER $SERVER "echo success"`;

if [ "success" = $CHK ] >/dev/null 2>&1
then
  ret=`ssh -n -t -q -o "BatchMode yes" -o "ConnectTimeout 5" -l $USER $SERVER '/home/username/timer.sh testvar;echo $?'`
  echo "return: [$ret]"
  if [ $ret -eq 0 ]; then
       echo "Success. Aborting"
       break
  fi
else
  printf "${i}\tUnable to connect to host\n";
fi
} < /dev/null; done

Hope it helps 希望能帮助到你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM