#!/bin/bash ##jsbk.sh ##email: jason [at] schaeferconsulting [dot] com ##505.570.1114 #dmy version version="aug 24 2021" ########################## USER EDIT BEGINS ############################# ## Email to, comma separated list for multiple recipients. host needs to be able to relay local mail. postfix recommended. to="backup@schaeferconsulting.com" from="support@schaeferconsulting.com" ## Set "yes" to rely on gnome volume manager (/media/[drivename]). Leave blank for manual mount (requires root priv. and will mount to /mnt) automount="" ## Name of drive. If you have multiple backup drives, they should be named the same. drivename="backup" ## Name of directory to write backups in. Leave blank to write to the root of backup drive. bkdir="" ## If you are in need of assistance, please contact [the following string] support="Schaefer Consulting at 505.570.1114" ## To bypass the backup commands, for debug purposes set to yes bypassbk="" ########################## START BACKUP COMMANDS ######################## backup_commands () { echo "Running backup commands now..." &>> $log ## Enter backup line's here i.e., cp, ssh, rsync #### ## append "||check" to the end of the command to verify if the command ran successfully ## == TAR == ## exmpl: /bin/tar zcvf $bklocation/$(/bin/date +%F).tar.gz --exclude media/* /home ||check &>> $log ## == CP == ## exmpl: /bin/cp -rvu /home/ $bklocation/new-n-changed ||check &>> $log ## == RSYNC == ## exmpl: /usr/bin/rsync -av --delete --stats --exclude media/* /home/ $bklocation/rsync-mirror ||check &>> $log ## == POSTGRES ## exmpl: /usr/bin/pg_dump -Z 9 -p 5432 -h hostname -U username dbname > $bklocation/dbname_$(/bin/date +%F_%T).sqldump.gz ||check &>> $log ## note: postgres auth uses ~/.pgpass containing localhost:5432:db:dbuser:dbpass ## == SMB == ## exmpl: cd $bklocation/backup-destination && /usr/bin/smbget -URq smb://user:password@hostname/share &>> $log ## == RDIFF-BACKUP == ## exmpl: /usr/bin/rdiff-backup --force --remove-older-than 10M $bklocation/rdiff-backup ||check &>> $log ## exmpl: /usr/bin/rdiff-backup /home $bklocation/rdiff-backup ||check &>> $log ## == RSNAPSHOT == ## Use the following options in rsnapshot.conf ## sync_first 1, no_create_root 1, link_dest 1 ## exmpl: /bin/sed -i -e "/^snapshot_root/s,/mnt/.*/\$,${bklocation}/rsnapshot/," /etc/rsnapshot.conf ## exmpl: /usr/bin/rsnapshot sync || { check &>> $log; return 1; } ## exmpl: [[ $(/bin/date +%d) == 01 ]] && { /usr/bin/rsnapshot delta || { check &>> $log; return 1; }; } ## exmpl: [[ $(/bin/date +%A) == Saturday ]] && { /usr/bin/rsnapshot gamma || { check &>> $log; return 1; }; } ## exmpl: /usr/bin/rsnapshot beta || { check &>> $log; return 1; } echo "rsnapshot of /home and /etc on $(hostname)" &>> $log #/bin/sed -i -e "/^snapshot_root/s,/.*\$,${bklocation}/rsnapshot/," /etc/rsnapshot.conf echo " sync..." &>> $log; /usr/bin/rsnapshot sync || { check &>> $log; return 1; } [[ $(/bin/date +%d) == 01 ]] && \ { echo " delta..." &>> $log; /usr/bin/rsnapshot delta || { check &>> $log; return 1; }; } [[ $(/bin/date +%A) == Saturday ]] && \ { echo " gamma..." &>> $log; /usr/bin/rsnapshot gamma || { check &>> $log; return 1; }; } echo " beta..." &>> $log; /usr/bin/rsnapshot beta || { check &>> $log; return 1; } echo "rsnapshot done" &>> $log } ########################### END BACKUP COMMANDS ######################### ########################### USER EDIT ENDS ############################## ########################### CRON REFERENCE ############################## ## setup to run on a schedule with cron ## minutes (0-59) | hours (0-23) | day of month (1-31) | month (1-12) | day of week (0-6 or Sun-Sat 0,6) | command ## 0 2 * * * /usr/local/bin/jsbk.sh ## will run at 2:00am every day ## 0 2 1,15 * * /usr/local/bin/jsbk.sh ## will run at 2:00am 1st and 15th of the month #if you want to see the log on your screen, use log="/dev/stdout" instead log="/tmp/jsbk.backup.log" #log="/dev/stdout" subject="Backup log from $(hostname)" #mountpoint, for easy reference later if [ "$automount" = "yes" ]; then mp="/media/$drivename"; else mp="/mnt"; fi #mount point plus backup dir, for easy reference in backup commands bklocation="$mp/$bkdir" starttime=$(/bin/date +%s) trap caughtsig 1 2 3 6 caughtsig () { echo "******************** Caught INTERRUPT SIG 1,2,3, or 6. **********************" &>> $log exit 1 } declare -g failed="" check () { echo "ERROR: A command FAILED!" &>> $log failed="failed" } error () { echo -e "*** Backup is NOT working!" &>> $log echo -e "*** Contact technician for service." &>> $log echo -e "*** Keep this message for diagnoses" &>> $log echo -e "*** Backup Failed on $(/bin/date +%c)\n" &>> $log echo -e "Mount Point: $mp\n" &>> $log #/bin/mount &>> $log } emailend () { #calculate running time of backup elapsed=$(($(/bin/date +%s) - $starttime)) printf "Elapsed running time: %dh:%dm:%ds\n" $(($elapsed/3600)) $(($elapsed%3600/60)) $(($elapsed%60)) &>> $log echo -e "\nBackup disk space (Size=total space, Used=space in use, Avail=space remaining; M=megabytes, G=gigabytes, T=terabytes):" &>> $log df -h $mp &>> $log #echo -e "\nLargest backed-up files that either are new or have changed since yesterday:" &>> $log #(cd $bklocation/ && /usr/bin/find * -type f -newermt yesterday -exec /bin/ls -dlS {} + |& head -n 4 &>> $log) echo -e "---\nIf you are in need of assistance, please contact $support\n" &>> $log if [ -z "$automount" ]; then /bin/umount $mp &>> $log || { echo -e "Error: Removing hard drive failed\n"; } &>> $log fi if [ -n "$to" ]; then /usr/bin/mail -r "$from" -s "$subject" $to < $log else echo "no email address specified" fi /bin/mv $log /tmp/jsbk.last.log exit } #check if backup is still running or exited without cleanup. if [ -f $log ]; then echo "log ($log) exists. this indicates that $0 may be currently running or exited uncleanly. verify with ps aux |grep $0 and if not running, delete $log." &>> $log error emailend fi [ "$automount" != yes -a -n "$automount" ] && echo ERROR: automount=\"$automount\" is not valid. &>> $log && error && emailend [ -z "$drivename" ] && echo ERROR: drivename is not declared &>> $log && error && emailend [ -z "$bkdir" ] && echo fyi, bkdir is not declared [ -z "$support" ] && echo fyi, support string is empty #begin echo "BACKUP LOG" &>> $log echo "version: $version" &>> $log echo "server: $(hostname)" &>> $log echo -e "Backup started on $(/bin/date +%c) \n" &>> $log if [ ! -d "$mp" ]; then echo "Mount point $mp does not exist!" &>> $log if [ "$automount" = "yes" ]; then echo "be sure drivename=\"$drivename\" is correct and gnome volume mounting is working. Or switch to automount=\"no\"" &>> $log fi if [ "$automount" = "no" ]; then echo "check that $mp exists" &>> $log fi echo "Also, be sure the drive is plugged in or turned on." &>> $log error emailend fi if [ -z "$automount" ]; then #mount drive manually at /mnt /bin/mount -o noatime -L $drivename $mp &>> $log || { echo "ERROR: mounting hard drive failed. Be sure drivename=\"$drivename\" is correct. Be sure the drive is plugged in or turned on."; error; emailend; } &>> $log fi if [ ! -d "$bklocation" ]; then echo bklocation=\"$bklocation\" is not a directory. stripping bkdir, will write files to root of $mp bkdir="" fi echo "+++ START LOG +++" &>> $log if [ "$bypassbk" = "yes" ]; then touch $bklocation/bypassbk.test echo "Bypassing all backup commands for debug purposes" &>> $log emailend else #user backup commands function backup_commands fi echo -e "+++ END LOG +++\n" &>> $log #check to see if $failed equals zero, if it is then all commands were successful. If not, something failed. if [ "$failed" = "failed" ]; then echo -e "\tERROR: A problem was detected!\n" &>> $log error else echo -e "\tSUCCESS: Backup Complete!\n" &>> $log fi emailend