#!/bin/bash

#Function:自动备份给定列表中的目录或文件,并且可以保留N天备份的档案。

#可备份至远程主机指定的目录下,但需本机能免密码登录到远程主机,用到ssh-keygen

#该脚本分为两个文件:执行文件backup.sh和备份项目文件bakfile.lst,两个文件必须位于同一目录下

#Author:JianJie

#Date:2016/8/26

#Usage:sudo bash backup.sh &

#Version:v2

###############################################################

logFile=/backup/local/log/`date +"%Y-%m"`.log #日志文件

logDir=/backup/local/log

myDate=`date +"%Y-%m-%d"`                     

bakFileLst=bakfile.lst            #需要备份的文件或目录放到该文件中

bakDir=/backup/local              #备份至此目录

keepDays=5                       #文件保留天数

remoteHost="rhel6.8:rhel7"     #需要备份至远程主机的地址,注意本机需免密码登陆到远程主机,多个主机地址或主机名之间用‘:’分割

remoteHostDir=/backup/$HOSTNAME    #远程主机备份目录

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"  #当前运行脚本所在的目录

###############################################################

#判断日志目录和日志文件是否存在

if [ ! -d $logDir ];then

  mkdir -p $logDir

  touch $logFile

else

  if [ ! -e $logFile ];then

  touch $logFile

  fi

fi

#开始记录日志

echo "Backup start at $(date +"%Y-%m-%d %H:%M:%S")" >> $logFile

echo "--------------------------------------------------------" >> $logFile

echo " " >> $logFile

#判断保存备份文件的文件列表'bakfile.lst'是否存在

if [ ! -e $currentDir/$bakFileLst ];then

  echo "Error:Important file [$currentDir/$bakFileLst] has been lost,now creating..." >> $logFile

  touch $currentDir/$bakFileLst

  echo "The file [$currentDir/$bakFileLst] has been created,but you still need to write data in it!" >> $logFile

  echo " " >> $logFile

  echo "--------------------------------------------------------" >> $logFile

  echo "Backup end at $(date +"%Y-%m-%d %H:%M:%S")" >> $logFile

  echo " " >> $logFile

  exit 3

fi

paths=`cat $currentDir/$bakFileLst`

for path in $paths

do

  baseName=`echo "$path" | xargs basename`

  oldFile=$bakDir/$baseName.$(date --date="$keepDays days ago" +"%Y-%m-%d").txz

  #判断路径中备份的是文件还是目录

  #若路径中要备份的是文件,则先进入指定路径中的上一级

  if [ -f "$path" ];then

    #进入指定路径中的上一级目录

    cd `echo "$path" | cut -d "/" -f 1-$(echo "$path"|gawk -F"/" '{print NF-1}')` 

    #若要备份的文件已经存在,则不再重复备份

    if [ -f $bakDir/$baseName.$myDate.txz ];then

      echo "Backup file [$bakDir/$baseName.$myDate.txz] already exists!" >> $logFile

    else

      cp -RHpf $baseName $bakDir

      cd  $bakDir

      #备份档案格式为.tar.xz,可根据需要调整,如.tar.gz或者.tar.bz2

      tar -cJf $baseName.$myDate.txz $baseName

      #将备份后的文件通过scp备份到远程主机

      for host in $(echo "$remoteHost" | sed 's/:/ /g')

      do

        scp -o ConnectTimeout=10 $baseName.$myDate.txz $host:$remoteHostDir >>$logFile 2>/dev/null && \

        echo "Successful backup [$path] to the remote host:[$host:$remoteHostDir]" >>$logFile || \

        echo "Backup [$path] to the remote host:[$host:$remoteHostDir] failed,please check it" >>$logFile

      done

        #备份完成,删除拷贝过来的源文件

        rm -rf $baseName

        echo "Backup [$path] done into [$bakDir] successfuly!" >> $logFile

        #若存在N天前旧文件,则删除它

        if [ -f $oldFile ];then

          rm -rf $oldFile

          echo "[$oldFile],delete old file successfuly!" >> $logFile

        fi

    fi

  #路径中备份的是目录

  elif [ -d "$path" ];then

     #先判断要备份的文件是否已经存在,若存在则不再重复备份

    if [ -f $bakDir/$baseName.$myDate.txz ];then

      echo "Backup file [$bakDir/$baseName.$myDate.txz] already exists!" >> $logFile

    else

      cd $path

      cd ..

      cp -RHpf $baseName $bakDir

      cd  $bakDir

      tar -cJf $baseName.$myDate.txz $baseName

      #将备份后的文件通过scp备份到远程主机

      for host in $(echo "$remoteHost" | sed 's/:/ /g')

      do

        scp -o ConnectTimeout=10 $baseName.$myDate.txz $host:$remoteHostDir >>$logFile 2>/dev/null && \

        echo "Successful backup [$path] to the remote host:[$host:$remoteHostDir]" >>$logFile || \

        echo "Backup [$path] to the remote host:[$host:$remoteHostDir] failed,please check it" >>$logFile

      done

        #备份完成,删除拷贝过来的源文件

        rm -rf $baseName

        echo "Backup [$path] done into [$bakDir] successfuly!" >> $logFile

        #若存在N天前旧文件,则删除它

        if [ -f $oldFile ];then

          rm -rf $oldFile

          echo "[$oldFile],delete old file successfuly!" >> $logFile

        fi

    fi

  else

    echo "Wrong path or file:[$path],please check it" >>$logFile

  fi

done

echo " " >> $logFile

echo "--------------------------------------------------------" >> $logFile

echo "Backup end at $(date +"%Y-%m-%d %H:%M:%S")" >> $logFile

echo " " >> $logFile

exit 0