From 392b8089a577054a5ee1042071ce0a120470d675 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Sat, 23 Nov 2013 01:07:31 -0800 Subject: Add a simple script for running rsync_tmbackup.sh from cron. --- cron_hourly_backup.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 cron_hourly_backup.sh diff --git a/cron_hourly_backup.sh b/cron_hourly_backup.sh new file mode 100644 index 0000000..526751f --- /dev/null +++ b/cron_hourly_backup.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# +# Installation instructions: +# +# 1. Declare where you installed rsync_tmbackup.sh to: + +TMBACKUP="/usr/local/bin/rsync_tmbackup.sh" + +# 2. Copy this script to /etc/cron.hourly +# +# 3. Run `sudo chmod 755 /etc/cron.hourly/cron_hourly_backup.sh` +# + +# Ubuntu Fedora +for DEST in /media/*/*/ /run/media/*/*/; do + [ -f "$DEST/backup.marker" ] || continue + USERNAME=$(basename $(dirname "$DEST")) + EXCLUDES=$(find /home/$USERNAME/.backup.excludes 2>/dev/null) + bash $TMBACKUP /home/$USERNAME $DEST $EXCLUDES +done -- cgit v1.2.3 From 9ece9fbec32d3050b5f85edb1625b14a61e31e61 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Sat, 23 Nov 2013 01:18:08 -0800 Subject: Fix spaces in filenames. --- cron_hourly_backup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cron_hourly_backup.sh b/cron_hourly_backup.sh index 526751f..8db0b8a 100644 --- a/cron_hourly_backup.sh +++ b/cron_hourly_backup.sh @@ -15,6 +15,6 @@ TMBACKUP="/usr/local/bin/rsync_tmbackup.sh" for DEST in /media/*/*/ /run/media/*/*/; do [ -f "$DEST/backup.marker" ] || continue USERNAME=$(basename $(dirname "$DEST")) - EXCLUDES=$(find /home/$USERNAME/.backup.excludes 2>/dev/null) - bash $TMBACKUP /home/$USERNAME $DEST $EXCLUDES + EXCLUDES=$(find "/home/$USERNAME/.backup.excludes" 2>/dev/null) + bash "$TMBACKUP" "/home/$USERNAME" "$DEST" "$EXCLUDES" done -- cgit v1.2.3 From 08d090f19c18321ad65682cfe3c35aba8431526f Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 12:41:42 -0800 Subject: Sort fn_find_backups newest first. --- rsync_tmbackup.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 8b2a0e1..b7bf2c0 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -40,7 +40,7 @@ fn_parse_date() { } fn_find_backups() { - find "$DEST_FOLDER" -type d -name "????-??-??-??????" -prune + find "$DEST_FOLDER" -type d -name "????-??-??-??????" -prune | sort -r } fn_expire_backup() { @@ -108,7 +108,7 @@ export IFS=$'\n' # Better for handling spaces in filenames. PROFILE_FOLDER="$HOME/.rsync_tmbackup" LOG_FILE="$PROFILE_FOLDER/$NOW.log" DEST=$DEST_FOLDER/$NOW -PREVIOUS_DEST=$(fn_find_backups | sort | tail -n 1) +PREVIOUS_DEST=$(fn_find_backups | head -n 1) INPROGRESS_FILE=$DEST_FOLDER/backup.inprogress # ----------------------------------------------------------------------------- @@ -129,10 +129,10 @@ if [ -f "$INPROGRESS_FILE" ]; then # - Last backup is moved to current backup folder so that it can be resumed. # - 2nd to last backup becomes last backup. fn_log_info "$INPROGRESS_FILE already exists - the previous backup failed or was interrupted. Backup will resume from there." - LINE_COUNT=$(fn_find_backups | sort | tail -n 2 | wc -l) + LINE_COUNT=$(fn_find_backups | wc -l) mv -- "$PREVIOUS_DEST" "$DEST" if [ "$LINE_COUNT" -gt 1 ]; then - PREVIOUS_PREVIOUS_DEST=$(fn_find_backups | sort | tail -n 2 | head -n 1) + PREVIOUS_PREVIOUS_DEST=$(fn_find_backups | sed -n '2p') PREVIOUS_DEST=$PREVIOUS_PREVIOUS_DEST else PREVIOUS_DEST="" @@ -173,7 +173,7 @@ while [ "1" ]; do # Default value for $prev ensures that the most recent backup is never deleted. prev="0000-00-00-000000" - for fname in $(fn_find_backups | sort -r); do + for fname in $(fn_find_backups); do date=$(basename "$fname") stamp=$(fn_parse_date $date) @@ -262,7 +262,7 @@ while [ "1" ]; do exit 1 fi - OLD_BACKUP_PATH=$(fn_find_backups | head -n 1) + OLD_BACKUP_PATH=$(fn_find_backups | tail -n 1) if [ "$OLD_BACKUP_PATH" == "" ]; then fn_log_error "No space left on device, and cannot get path to oldest backup to delete." exit 1 -- cgit v1.2.3 From 16fd955e6ce1cc90f7e5f0842f50d702ed60adc5 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 12:43:58 -0800 Subject: Drop some single-use variables. --- rsync_tmbackup.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index b7bf2c0..70789ca 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -129,11 +129,9 @@ if [ -f "$INPROGRESS_FILE" ]; then # - Last backup is moved to current backup folder so that it can be resumed. # - 2nd to last backup becomes last backup. fn_log_info "$INPROGRESS_FILE already exists - the previous backup failed or was interrupted. Backup will resume from there." - LINE_COUNT=$(fn_find_backups | wc -l) mv -- "$PREVIOUS_DEST" "$DEST" - if [ "$LINE_COUNT" -gt 1 ]; then - PREVIOUS_PREVIOUS_DEST=$(fn_find_backups | sed -n '2p') - PREVIOUS_DEST=$PREVIOUS_PREVIOUS_DEST + if [ "$(fn_find_backups | wc -l)" -gt 1 ]; then + PREVIOUS_DEST="$(fn_find_backups | sed -n '2p')" else PREVIOUS_DEST="" fi -- cgit v1.2.3 From 45875055a43803c0fd372e4948e91ca2db80afab Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 12:45:12 -0800 Subject: Simpler absolute paths. --- rsync_tmbackup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 70789ca..0d087bc 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -151,7 +151,7 @@ while [ "1" ]; do else # If the path is relative, it needs to be relative to the destination. To keep # it simple, just use an absolute path. See http://serverfault.com/a/210058/118679 - PREVIOUS_DEST=`cd \`dirname -- "$PREVIOUS_DEST"\`; pwd`"/"`basename -- "$PREVIOUS_DEST"` + PREVIOUS_DEST="$(cd "$PREVIOUS_DEST"; pwd)" fn_log_info "Previous backup found - doing incremental backup from $PREVIOUS_DEST" LINK_DEST_OPTION="--link-dest=$PREVIOUS_DEST" fi -- cgit v1.2.3 From 4da71720994ab3623cdebced17cbb1da7e8d1b41 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 12:46:15 -0800 Subject: Redundant. --- rsync_tmbackup.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 0d087bc..05c8fa8 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -106,7 +106,6 @@ KEEP_DAILIES_DATE=$(($EPOCH - 2678400)) # 31 days ago export IFS=$'\n' # Better for handling spaces in filenames. PROFILE_FOLDER="$HOME/.rsync_tmbackup" -LOG_FILE="$PROFILE_FOLDER/$NOW.log" DEST=$DEST_FOLDER/$NOW PREVIOUS_DEST=$(fn_find_backups | head -n 1) INPROGRESS_FILE=$DEST_FOLDER/backup.inprogress -- cgit v1.2.3 From c3f15c7834c42c5fc7575a8e611848441ee031e5 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 12:48:49 -0800 Subject: Simplify symlink creation. --- rsync_tmbackup.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 05c8fa8..5d3439e 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -280,10 +280,8 @@ while [ "1" ]; do # Add symlink to last successful backup # ----------------------------------------------------------------------------- - cd "$DEST_FOLDER" - rm -f -- "latest" - ln -s -- $(basename -- "$DEST") "latest" - cd - + rm -rf -- "$DEST_FOLDER/latest" + ln -vs -- "$NOW" "$DEST_FOLDER/latest" rm -- "$INPROGRESS_FILE" # TODO: grep for "^rsync error:.*$" in log -- cgit v1.2.3 From 0db8b3a913ff2cd890584284f1408ba095fb8e43 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 12:55:17 -0800 Subject: Define trivial functions on one line only. --- rsync_tmbackup.sh | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 5d3439e..4a42b1f 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -4,24 +4,16 @@ # Log functions # ----------------------------------------------------------------------------- -fn_log_info() { - echo "rsync_tmbackup: $1" -} - -fn_log_warn() { - echo "rsync_tmbackup: [WARNING] $1" -} - -fn_log_error() { - echo "rsync_tmbackup: [ERROR] $1" -} +fn_log_info() { echo "rsync_tmbackup: $1"; } +fn_log_warn() { echo "rsync_tmbackup: [WARNING] $1"; } +fn_log_error() { echo "rsync_tmbackup: [ERROR] $1"; } # ----------------------------------------------------------------------------- # Make sure everything really stops when CTRL+C is pressed # ----------------------------------------------------------------------------- fn_terminate_script() { - echo "rsync_tmbackup: SIGINT caught." + fn_log_info "SIGINT caught." exit 1 } @@ -46,7 +38,7 @@ fn_find_backups() { fn_expire_backup() { # Double-check that we're on a backup destination to be completely # sure we're deleting the right folder - if [ -z "$(fn_is_backup_destination "$(dirname -- "$1")")" ]; then + if [ -z "$(fn_find_backup_marker "$(dirname -- "$1")")" ]; then fn_log_error "$1 is not on a backup destination - aborting." exit 1 fi @@ -76,15 +68,10 @@ done # TODO: check that the destination supports hard links -fn_backup_marker_path() { - echo "$1/backup.marker" -} - -fn_is_backup_destination() { - find "$(fn_backup_marker_path "$1")" 2>/dev/null -} +fn_backup_marker_path() { echo "$1/backup.marker"; } +fn_find_backup_marker() { find "$(fn_backup_marker_path "$1")" 2>/dev/null; } -if [ -z "$(fn_is_backup_destination $DEST_FOLDER)" ]; then +if [ -z "$(fn_find_backup_marker "$DEST_FOLDER")" ]; then fn_log_info "Safety check failed - the destination does not appear to be a backup folder or drive (marker file not found)." fn_log_info "If it is indeed a backup folder, you may add the marker file by running the following command:" fn_log_info "" -- cgit v1.2.3 From e5f939222e2d6be96e12e172dfeaa633fc296f42 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 12:59:00 -0800 Subject: Determine $APPNAME programmatically. --- rsync_tmbackup.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 4a42b1f..ed203b6 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -1,12 +1,14 @@ #!/usr/bin/env bash +APPNAME=$(basename $0 | sed "s/\.sh$//") + # ----------------------------------------------------------------------------- # Log functions # ----------------------------------------------------------------------------- -fn_log_info() { echo "rsync_tmbackup: $1"; } -fn_log_warn() { echo "rsync_tmbackup: [WARNING] $1"; } -fn_log_error() { echo "rsync_tmbackup: [ERROR] $1"; } +fn_log_info() { echo "$APPNAME: $1"; } +fn_log_warn() { echo "$APPNAME: [WARNING] $1"; } +fn_log_error() { echo "$APPNAME: [ERROR] $1"; } # ----------------------------------------------------------------------------- # Make sure everything really stops when CTRL+C is pressed @@ -92,7 +94,7 @@ KEEP_DAILIES_DATE=$(($EPOCH - 2678400)) # 31 days ago export IFS=$'\n' # Better for handling spaces in filenames. -PROFILE_FOLDER="$HOME/.rsync_tmbackup" +PROFILE_FOLDER="$HOME/.$APPNAME" DEST=$DEST_FOLDER/$NOW PREVIOUS_DEST=$(fn_find_backups | head -n 1) INPROGRESS_FILE=$DEST_FOLDER/backup.inprogress -- cgit v1.2.3 From 40e5ce472160762718a3e6de9390404cbd80545a Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 13:02:29 -0800 Subject: Use bash : noop for efficiency. --- rsync_tmbackup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index ed203b6..4078916 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -127,7 +127,7 @@ if [ -f "$INPROGRESS_FILE" ]; then fi # Run in a loop to handle the "No space left on device" logic. -while [ "1" ]; do +while : ; do # ----------------------------------------------------------------------------- # Check if we are doing an incremental backup (if previous backup exists) or not @@ -167,7 +167,7 @@ while [ "1" ]; do [ -n "$stamp" ] || continue if [ $stamp -ge $KEEP_ALL_DATE ]; then - true + : # Don't expire any backups in this range elif [ $stamp -ge $KEEP_DAILIES_DATE ]; then # Delete all but the most recent of each day. -- cgit v1.2.3 From 2f0092ac9fab2c8d4ab205b9893d6a48f2437da2 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 13:04:30 -0800 Subject: Use -n and -z for easier string emptiness checks. --- rsync_tmbackup.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 4078916..08f98f8 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -113,7 +113,7 @@ fi # ----------------------------------------------------------------------------- if [ -f "$INPROGRESS_FILE" ]; then - if [ "$PREVIOUS_DEST" != "" ]; then + if [ -n "$PREVIOUS_DEST" ]; then # - Last backup is moved to current backup folder so that it can be resumed. # - 2nd to last backup becomes last backup. fn_log_info "$INPROGRESS_FILE already exists - the previous backup failed or was interrupted. Backup will resume from there." @@ -134,7 +134,7 @@ while : ; do # ----------------------------------------------------------------------------- LINK_DEST_OPTION="" - if [ "$PREVIOUS_DEST" == "" ]; then + if [ -z "$PREVIOUS_DEST" ]; then fn_log_info "No previous backup - creating new one." else # If the path is relative, it needs to be relative to the destination. To keep @@ -203,7 +203,7 @@ while : ; do CMD="$CMD --itemize-changes" CMD="$CMD --verbose" CMD="$CMD --log-file '$LOG_FILE'" - if [ "$EXCLUSION_FILE" != "" ]; then + if [ -n "$EXCLUSION_FILE" ]; then # We've already checked that $EXCLUSION_FILE doesn't contain a single quote CMD="$CMD --exclude-from '$EXCLUSION_FILE'" fi @@ -249,7 +249,7 @@ while : ; do fi OLD_BACKUP_PATH=$(fn_find_backups | tail -n 1) - if [ "$OLD_BACKUP_PATH" == "" ]; then + if [ -z "$OLD_BACKUP_PATH" ]; then fn_log_error "No space left on device, and cannot get path to oldest backup to delete." exit 1 fi -- cgit v1.2.3 From 4720f404afc1ddded26a7b40a68b5289cc05d3b0 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 13:08:52 -0800 Subject: Extra quotes everywhere! --- rsync_tmbackup.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 08f98f8..be4c982 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -53,9 +53,9 @@ fn_expire_backup() { # Source and destination information # ----------------------------------------------------------------------------- -SRC_FOLDER=${1%/} -DEST_FOLDER=${2%/} -EXCLUSION_FILE=$3 +SRC_FOLDER="${1%/}" +DEST_FOLDER="${2%/}" +EXCLUSION_FILE="$3" for arg in "$SRC_FOLDER" "$DEST_FOLDER" "$EXCLUSION_FILE"; do if [[ "$arg" == *"'"* ]]; then @@ -95,9 +95,9 @@ KEEP_DAILIES_DATE=$(($EPOCH - 2678400)) # 31 days ago export IFS=$'\n' # Better for handling spaces in filenames. PROFILE_FOLDER="$HOME/.$APPNAME" -DEST=$DEST_FOLDER/$NOW -PREVIOUS_DEST=$(fn_find_backups | head -n 1) -INPROGRESS_FILE=$DEST_FOLDER/backup.inprogress +DEST="$DEST_FOLDER/$NOW" +PREVIOUS_DEST="$(fn_find_backups | head -n 1)" +INPROGRESS_FILE="$DEST_FOLDER/backup.inprogress" # ----------------------------------------------------------------------------- # Create profile folder if it doesn't exist @@ -248,7 +248,7 @@ while : ; do exit 1 fi - OLD_BACKUP_PATH=$(fn_find_backups | tail -n 1) + OLD_BACKUP_PATH="$(fn_find_backups | tail -n 1)" if [ -z "$OLD_BACKUP_PATH" ]; then fn_log_error "No space left on device, and cannot get path to oldest backup to delete." exit 1 -- cgit v1.2.3 From b16c3cf4ceada6a1bfb7e71e19605d723d1d51d5 Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 13:11:53 -0800 Subject: Even more quotes. --- rsync_tmbackup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 8e94931..ba12a18 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -77,7 +77,7 @@ if [ -z "$(fn_find_backup_marker "$DEST_FOLDER")" ]; then fn_log_info "Safety check failed - the destination does not appear to be a backup folder or drive (marker file not found)." fn_log_info "If it is indeed a backup folder, you may add the marker file by running the following command:" fn_log_info "" - fn_log_info "touch \"$(fn_backup_marker_path $DEST_FOLDER)\"" + fn_log_info "touch \"$(fn_backup_marker_path "$DEST_FOLDER")\"" fn_log_info "" exit 1 fi -- cgit v1.2.3 From d73b3ffe43de1931bb419aef0255ca1ffa401e0c Mon Sep 17 00:00:00 2001 From: Robert Bruce Park Date: Tue, 26 Nov 2013 13:13:58 -0800 Subject: Yet more quotes! --- rsync_tmbackup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index ba12a18..3d0b947 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -140,7 +140,7 @@ while : ; do # it simple, just use an absolute path. See http://serverfault.com/a/210058/118679 PREVIOUS_DEST="$(cd "$PREVIOUS_DEST"; pwd)" fn_log_info "Previous backup found - doing incremental backup from $PREVIOUS_DEST" - LINK_DEST_OPTION="--link-dest=$PREVIOUS_DEST" + LINK_DEST_OPTION="--link-dest='$PREVIOUS_DEST'" fi # ----------------------------------------------------------------------------- -- cgit v1.2.3 From c854cd17c6c6c76de4ec2cae365e0b6fd9e7f1cf Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Wed, 27 Nov 2013 12:36:54 +0800 Subject: Restoring `$(basename -- "$DEST")` In case the destination is later on generated in a different way, also makes the code and intention more explicit. --- rsync_tmbackup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rsync_tmbackup.sh b/rsync_tmbackup.sh index 3d0b947..c49d8f2 100644 --- a/rsync_tmbackup.sh +++ b/rsync_tmbackup.sh @@ -262,7 +262,7 @@ while : ; do # ----------------------------------------------------------------------------- rm -rf -- "$DEST_FOLDER/latest" - ln -vs -- "$NOW" "$DEST_FOLDER/latest" + ln -vs -- "$(basename -- "$DEST")" "$DEST_FOLDER/latest" rm -f -- "$INPROGRESS_FILE" # TODO: grep for "^rsync error:.*$" in log -- cgit v1.2.3