Shell backup script – Windows SMB / Linux Server

prepare

  • copy all files in one folder
  • modify backup-start.sh with your path and configs
  • make a btrfs partition
  • create a subvolume for the backup path
  • create a cronjob

start

backup-start.sh daily
backup-start.sh weekly

backup modes

  • smb
  • sshs
  • sshnosymlink
  • sshsudoftp

backup-start.sh

#!/bin/bash
# check the backup script if its running and if yes then calc for a snapshot
script_name=/home/backup/backup-script.sh
email_admin=mail1@mail.de,mail2@mail.de
backup_path=/srv/backup/done
snapshot_path=/srv/backup/snapshots/backup-$(date +%Y-%m-%d-%H-%M)
snapshot_script=/home/eit/backup/services-snapshots.sh

## script start

if [ -z "$1" ];then
 echo "no target set"
 exit 1
else
 #echo "Set Target"
 backup_mode=$1
fi

## function for the errpr codes
check_error(){
 if [ "$1" -ge "100" ]; then
 echo "Start - Backup still running"
 exit 1
 fi
 if [ "$1" -eq "10" ]; then
 echo "Start - Backup done - no files"
 MODE=$backup_mode $snapshot_script $backup_local_path/$server $snapshot_local_path/$server
 else
 if [ "$1" -eq "0" ]; then
 echo "Start - Backup done - with files"
 MODE=$backup_mode $snapshot_script $backup_local_path/$server $snapshot_local_path/$server
 fi
 fi
}

script_start(){
 if [ ! -d "$backup_local_path/$server" ]; then
 echo "backup folder not exist"
 btrfs subvolume create $backup_local_path/$server
 chmod 740 $backup_local_path/$server
 echo "backup folder created"
 else
 echo "backup folder exist"
 fi
}

##
# run backup script
##

server=mysvwe1
script_start
sh $script_name $email_admin $server /path/to/backup/data $backup_local_path ssh username password
error_now=$?
check_error $error_now

exit 0

backup-script.sh

#!/bin/bash
#
# Thomas Mosandl - 2014-11-14
#
# apt-get install cifs-utils sendmail-bin
# sendmail config
#
# define parameter#!/bin/sh
# define parameterss
## variablen
## 1. mail to
## 2. backup_source_ip
## 3. backup_source_path
## 4. backup_dest_path

backup_source_ip=$2
backup_source_path=$3
backup_source_user=$6
backup_source_domain='asd'
backup_source_pw=$7
backup_log_path=/var/log
backup_check_client_ping="1"
backup_service=$5
backup_dest_path=$4/$backup_source_ip
backup_log_path=/var/log
backup_log_file=backup_$backup_source_ip
backup_email_to_config="thomas.mosandl@mosandl.eu"
backup_email_from="backup@mosandl.eu"

# end config

echo "Backup Start - $backup_source_ip"

# vaiable check
if [ -z "$1" ];then
        echo "mail set to config"
        backup_email_to="$backup_email_to_config"
else
        echo "mail set to parameter"
        backup_email_to=$1
fi
# check iscsi target


#ping -q -c$backup_check_client_ping $backup_iscsi_target_1 > /dev/null
#if [ ! $? -eq 0 ]; then
#	echo "ISCSI Ping not availible"
#	echo " "  | mail -s "Backup - ISCSI - Ping is not working" -a "From: $backup_email_from" $backup_email_to
#	exit 1
#else
#	#if [ $(iscsiadm -m session | grep -c "$backup_iscsi_target_1") -eq 0 ]; then
	#	echo "ISCSI Mount not availible"
	#	echo " "  | mail -s "Backup - ISCSI - Mount is not working" -a "From: $backup_email_from" $backup_email_to
	#	exit 1
	#else
#		echo "ISCSI is okay"
	#fi
#fi

#192.168.144.167
# check if backup is running
ps aux > /tmp/temp.txt
if [ $(cat /tmp/temp.txt  | grep -c "ssh -o StrictHostKeyChecking=no -l")  -gt 0 ]; then
	echo "backup was broken or not running"
	if [ -f "$backup_log_path/$backup_log_file.lck" ]; then
		rm -rf "$backup_log_path/$backup_log_file.lck"
	fi
fi
rm -rf /tmp/temp.txt

if [ -f "$backup_log_path/$backup_log_file.lck" ]; then
		echo " "  | mail -s "Backup - $backup_source_ip - Backup is still running"  -r  $backup_email_from  $backup_email_to
		echo "Script - backup is running"
		set -e
		exit 100
else
	echo "Script - backup is not still running"
	touch "$backup_log_path/$backup_log_file.lck"
fi

# check if log is in logrotate

if [ $(grep -c "$backup_log_path/$backup_log_file" /etc/logrotate.d/rsyslog)  -eq 1 ]; then
	echo "Script - rsyslog is set"
else
	echo "$backup_log_path/$backup_log_file {}" >> /etc/logrotate.d/rsyslog
	echo "Script - rsyslog created"
fi

#
if [ ! $(mount | grep -c "/media/data0/srv/backup type btrfs (rw)")  -eq 0 ]; then
	echo "storage not mounted"
	exit 11
	echo " "  | mail -s "Backup - storage not mounted"  -r  $backup_email_from  $backup_email_to
else
	echo "storage is mounted"
fi

# create folders

# check backup dir
if [ ! -d "$backup_dest_path" ]; then
      echo "backup folder not exist"
      mkdir -p $backup_dest_path
      chmod 740 $backup_dest_path
      echo "backup folder created"
else
      echo "backup folder exist"
fi


if [ ! -d "$backup_log_path" ]; then
      echo "backup log folder not exist"
      mkdir -p $backup_log_path
      echo "backup log folder created"
else
      echo "backup log folder exist"
fi





# nslookup check
nslookup $backup_source_ip > /dev/null
if [ ! $? -eq 0 ]; then
	echo "DNS is not working for $backup_source_ip"
	echo " "  | mail -s "Backup - $backup_source_ip - nslookup is not working for $backup_source_ip"  -r  $backup_email_from  $backup_email_to
	rm -rf "$backup_log_path/$backup_log_file.lck"
	set -e
	exit 1
else
	echo "DNS is okay"
fi


# ping check
if [ ! $backup_source_ip = "server.de" ]; then
	ping -q -c$backup_check_client_ping $backup_source_ip > /dev/null
		if [ ! $? -eq 0 ]; then
		echo "PING is not working for $backup_source_ip"
		echo " "  | mail -s "Backup - $backup_source_ip - ping $backup_source_ip is not working"  -r  $backup_email_from  $backup_email_to
		rm -rf "$backup_log_path/$backup_log_file.lck"
		set -e
		exit 1
	else
		echo "Ping is okay"
	fi
fi

# rsync
echo  $backup_service
if [ $backup_service = ssh ]; then
	exit_code="0"
	log_file_temp=$backup_log_file_$(date +%Y_%m_%d_%H_%M_%S)
	export SSHPASS=$backup_source_pw
	ionice -c 3 rsync -rptgoDvzLKh --delete --rsh="/usr/bin/sshpass -e ssh -o StrictHostKeyChecking=no -l $backup_source_user " $backup_source_ip:$backup_source_path  $backup_dest_path --log-file=$backup_log_path/$log_file_temp --stats >> $backup_log_path/$log_file_temp
	if [ ! $? -ge 0 ]; then
		echo "Backup error - $?"
		cat -v $backup_log_path/$backup_log_file | mail -s "Backup - $backup_source_ip - Error Backup - $?" -a "From: $backup_email_from" $backup_email_to
		set -e
		exit 1
	else
		echo "Backup is okay"
		if [ ! $(grep -c "Number of created files: 0" $backup_log_path/$log_file_temp) -eq 0 ]; then
			 mail -s "Backup - $backup_source_ip - Done Backup - no files" -r  $backup_email_from   $backup_email_to < $backup_log_path/$log_file_temp
			 echo "Script - no files"
			 exit_code="10"
		 else
			 cat -v  $backup_log_path/$log_file_temp | mail -s "Backup - $backup_source_ip - Done Backup"  -r  $backup_email_from  $backup_email_to
		 fi
		 cat  $backup_log_path/$log_file_temp >>  $backup_log_path/$backup_log_file
		 rm  $backup_log_path/$log_file_temp
	 fi
elif [ $backup_service = sshnosymlink ]; then
	 exit_code="0"
	 log_file_temp=$backup_log_file_$(date +%Y_%m_%d_%H_%M_%S)
	 export SSHPASS=$backup_source_pw
	 ionice -c 3 rsync -rptgoDvzlKh --delete --rsh="/usr/bin/sshpass -e ssh -o StrictHostKeyChecking=no -l $backup_source_user " $backup_source_ip:$backup_source_path  $backup_dest_path --log-file=$backup_log_path/$log_file_temp --stats >> $backup_log_path/$log_file_temp
	 if [ ! $? -ge 0 ]; then
		 echo "Backup error - $?"
		 cat -v $backup_log_path/$backup_log_file | mail -s "Backup - $backup_source_ip - Error Backup - $?" -a "From: $backup_email_from" $backup_email_to
		 set -e
		 exit 1
	 else
		 echo "Backup is okay"
		 if [ ! $(grep -c "Number of created files: 0" $backup_log_path/$log_file_temp) -eq 0 ]; then
			 mail -s "Backup - $backup_source_ip - Done Backup - no files" -r  $backup_email_from   $backup_email_to < $backup_log_path/$log_file_temp
			 echo "Script - no files"
			 exit_code="10"
		 else
			 cat -v  $backup_log_path/$log_file_temp | mail -s "Backup - $backup_source_ip - Done Backup"  -r  $backup_email_from  $backup_email_to
		 fi
		 cat  $backup_log_path/$log_file_temp >>  $backup_log_path/$backup_log_file
		 rm  $backup_log_path/$log_file_temp
	 fi
elif [ $backup_service = sshsudoftp ]; then
	 exit_code="0"
	 log_file_temp=$backup_log_file_$(date +%Y_%m_%d_%H_%M_%S)
	 export SSHPASS=$backup_source_pw
	 ionice -c 3 rsync -rptgoDzLKh --delete --exclude "*users/data*" --exclude "*users/*/data*"  --rsync-path="sudo rsync" --rsh="/usr/bin/sshpass -e ssh -o StrictHostKeyChecking=no -l $backup_source_user " $backup_source_ip:$backup_source_path  $backup_dest_path --log-file=$backup_log_path/$log_file_temp --stats >> $backup_log_path/$log_file_temp
	 if [ ! $? -ge 0 ]; then
		 echo "Backup error - $?"
		 cat -v $backup_log_path/$backup_log_file | mail -s "Backup - $backup_source_ip - Error Backup - $?" -a "From: $backup_email_from" $backup_email_to
		 set -e
		 exit 1
	 else
		 echo "Backup is okay"
		 if [ ! $(grep -c "Number of created files: 0" $backup_log_path/$log_file_temp) -eq 0 ]; then
			  mail -s "Backup - $backup_source_ip - Done Backup - no files" -r  $backup_email_from   $backup_email_to < $backup_log_path/$log_file_temp
			  echo "Script - no files"
			  exit_code="10"
		  else
			  cat -v  $backup_log_path/$log_file_temp | mail -s "Backup - $backup_source_ip - Done Backup"  -r  $backup_email_from  $backup_email_to
		  fi
		  cat  $backup_log_path/$log_file_temp >>  $backup_log_path/$backup_log_file
		  rm  $backup_log_path/$log_file_temp
	  fi

elif [ $backup_service = smb ]; then
        # mount backup
        mount -t cifs //$backup_source_ip/$backup_source_path $backup_mount_path -o username=$backup_source_user,password=$backup_source_pw,ro,sec=ntlm

        if [ ! $? -eq 0 ]; then
                echo "Mount is not okay - $?"
                echo " "  | mail -s "Backup - $backup_source_ip - mount -t cifs //$backup_source_ip/$backup_source_path $backup_mount_path  is not working" -a "From: $backup_email_from" $backup_email_to
                rm -rf "$backup_log_path/$backup_log_file.lck"
                set -e
                exit 1
        else
                echo "Mount is okay"
        fi


        # rsync
        exit_code="0"
        log_file_temp=$backup_log_file_$(date +%Y_%m_%d_%H_%M_%S)
        rsync -rlptDvz $backup_mount_path $backup_dest_path --log-file=$backup_log_path/$log_file_temp --stats --chmod=u=rwx,g=rx,o=rx >> $backup_log_path/$log_file_temp
        if [ ! $? -ge 0 ]; then
                echo "Backup error - $?"
                cat -v $backup_log_path/$backup_log_file | mail -s "Backup - $backup_source_ip - Error Backup - $?" -a "From: $backup_email_from" $backup_email_to
                set -e
                exit 1
        else
                echo "Backup is okay"
                                                                                                                     199,2-9       92%
        else
                echo "Backup is okay"
                if [ ! $(grep -c "Number of created files: 0" $backup_log_path/$log_file_temp) -eq 0 ]; then
                        cat -v  $backup_log_path/$log_file_temp | mail -s "Backup - $backup_source_ip - Done Backup - no files" -a "From: $backup_email_from" $backup_email_to
                        echo "Script - no files"
                        exit_code="10"
                else
                        cat -v  $backup_log_path/$log_file_temp | mail -s "Backup - $backup_source_ip - Done Backup" -a "From: $backup_email_from" $backup_email_to
                fi
                cat  $backup_log_path/$log_file_temp >>  $backup_log_path/$backup_log_file
                rm  $backup_log_path/$log_file_temp
        fi
fi

# unmount

rm -rf "$backup_log_path/$backup_log_file.lck"
exit $exit_code

services-snapshots.sh

#!/bin/bash
set -e

if [[ -z $MODE ]]; then
	echo "$MODE not specified"
	exit 1
fi

if [[ $UID -ne 0 ]]; then
	echo "Must be run as root"
	exit 1
fi

if [ -z "$1" ];then
	echo "not sources set"
	exit 1
else
	echo "Set Source"
	BACKUP_SOURCE_DIR=$1

fi

if [ -z "$2" ];then
	echo "no target set"
	exit 1
else
	echo "Set Target"
	BACKUP_BASE_DIR=$2
fi

BACKUP_DIR_DAILY=${BACKUP_BASE_DIR}/daily
BACKUP_DIR_WEEKLY=${BACKUP_BASE_DIR}/weekly
BACKUP_DIR_MONTHLY=${BACKUP_BASE_DIR}/monthly
BACKUP_DIR_YEARLY=${BACKUP_BASE_DIR}/yearly

if [ ! -d "$BACKUP_DIR_DAILY" ]; then
	echo "backup folder not exist"
	mkdir -p $BACKUP_DIR_DAILY
	chmod 740 $BACKUP_DIR_DAILY
	echo "backup folder created"
else
	echo "backup folder exist"
fi
if [ ! -d "$BACKUP_DIR_WEEKLY" ]; then
	echo "backup folder not exist"
	mkdir -p $BACKUP_DIR_WEEKLY
	chmod 740 $BACKUP_DIR_WEEKLY
	echo "backup folder created"
else
	echo "backup folder exist"
fi
if [ ! -d "$BACKUP_DIR_MONTHLY" ]; then
	echo "backup folder not exist"
	mkdir -p $BACKUP_DIR_MONTHLY
	chmod 740 $BACKUP_DIR_MONTHLY
	echo "backup folder created"
else
	echo "backup folder exist"
fi
if [ ! -d "$BACKUP_DIR_YEARLY" ]; then
	echo "backup folder not exist"
	mkdir -p $BACKUP_DIR_YEARLY
	chmod 740 $BACKUP_DIR_YEARLY
	echo "backup folder created"
else
	echo "backup folder exist"
fi




NUM_FILES_TO_KEEP_DAILY=10
NUM_FILES_TO_KEEP_WEEKLY=20
NUM_FILES_TO_KEEP_MONTHLY=12
NUM_FILES_TO_KEEP_YEARLY=10

if [[ $MODE = "DAILY" ]]; then
	BACKUP_DIR=$BACKUP_DIR_DAILY
	NUM_FILES_TO_KEEP=$NUM_FILES_TO_KEEP_DAILY
elif [[ $MODE = "WEEKLY" ]]; then
	BACKUP_DIR=$BACKUP_DIR_WEEKLY
	NUM_FILES_TO_KEEP=$NUM_FILES_TO_KEEP_WEEKLY
elif [[ $MODE = "MONTHLY" ]]; then
	BACKUP_DIR=$BACKUP_DIR_MONTHLY
	NUM_FILES_TO_KEEP=$NUM_FILES_TO_KEEP_MONTHLY
elif [[ $MODE = "YEARLY" ]]; then
	BACKUP_DIR=$BACKUP_DIR_YEARLY
	NUM_FILES_TO_KEEP=$NUM_FILES_TO_KEEP_YEARLY
else
	echo "available $MODE values are: DAILY, MONTHLY, WEEKLY, YEARLY"
	exit 1
fi

NUM_FILES_TO_KEEP=$(( $NUM_FILES_TO_KEEP + 1 ))

_backup () {
	/sbin/btrfs subvolume snapshot -r $BACKUP_SOURCE_DIR ${BACKUP_DIR}/backup-$(date +%Y-%m-%d)
}

_cleanup () {
	for file in $(ls -rt $BACKUP_DIR | tail -n  +${NUM_FILES_TO_KEEP} ); do
		sudo btrfs subvolume delete ${BACKUP_DIR}/$file
	done
}

_backup
_cleanup