Rebase on @laurent22/master.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Rsync time backup
|
# Rsync time backup
|
||||||
|
|
||||||
Time Machine style backup with rsync. Should work on Linux, Mac OS X and Windows with Cygwin.
|
Time Machine style backup with rsync. Should work on Linux (tested on some distros), Mac OS X (fully tested) and Windows with Cygwin (not tested yet but feeback would be welcome).
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
@@ -36,12 +36,18 @@ An optional exclude file can be provided as a third parameter. It should be comp
|
|||||||
|
|
||||||
* Exclude file - support for pattern-based exclusion via the `--exclude-from` rsync parameter.
|
* Exclude file - support for pattern-based exclusion via the `--exclude-from` rsync parameter.
|
||||||
|
|
||||||
* The application is one bash script that can be easily edited.
|
* Automatically purge old backups - within 24 hours, all backups are kept. Within one month, the most recent backup for each day is kept. For all previous backups, the most recent of each month is kept.
|
||||||
|
|
||||||
|
* "latest" symlink that points to the latest successful backup.
|
||||||
|
|
||||||
|
* The application is just one bash script that can be easily edited.
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
* Minor changes (see TODO comments in the source).
|
* Minor changes (see TODO comments in the source).
|
||||||
|
|
||||||
|
* Backup to remote drive?
|
||||||
|
|
||||||
# LICENSE
|
# LICENSE
|
||||||
|
|
||||||
[MIT](http://opensource.org/licenses/MIT)
|
[MIT](http://opensource.org/licenses/MIT)
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
#!/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
|
|
||||||
+24
-32
@@ -57,8 +57,8 @@ SRC_FOLDER="${1%/}"
|
|||||||
DEST_FOLDER="${2%/}"
|
DEST_FOLDER="${2%/}"
|
||||||
EXCLUSION_FILE="$3"
|
EXCLUSION_FILE="$3"
|
||||||
|
|
||||||
for arg in "$SRC_FOLDER" "$DEST_FOLDER" "$EXCLUSION_FILE"; do
|
for ARG in "$SRC_FOLDER" "$DEST_FOLDER" "$EXCLUSION_FILE"; do
|
||||||
if [[ "$arg" == *"'"* ]]; then
|
if [[ "$ARG" == *"'"* ]]; then
|
||||||
fn_log_error 'Arguments may not have any single quote characters.'
|
fn_log_error 'Arguments may not have any single quote characters.'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -92,7 +92,6 @@ EPOCH=$(date "+%s")
|
|||||||
KEEP_ALL_DATE=$(($EPOCH - 86400)) # 1 day ago
|
KEEP_ALL_DATE=$(($EPOCH - 86400)) # 1 day ago
|
||||||
KEEP_DAILIES_DATE=$(($EPOCH - 2678400)) # 31 days ago
|
KEEP_DAILIES_DATE=$(($EPOCH - 2678400)) # 31 days ago
|
||||||
|
|
||||||
|
|
||||||
export IFS=$'\n' # Better for handling spaces in filenames.
|
export IFS=$'\n' # Better for handling spaces in filenames.
|
||||||
PROFILE_FOLDER="$HOME/.$APPNAME"
|
PROFILE_FOLDER="$HOME/.$APPNAME"
|
||||||
DEST="$DEST_FOLDER/$NOW"
|
DEST="$DEST_FOLDER/$NOW"
|
||||||
@@ -130,7 +129,7 @@ fi
|
|||||||
while : ; do
|
while : ; do
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Check if we are doing an incremental backup (if previous backup exists) or not
|
# Check if we are doing an incremental backup (if previous backup exists).
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
LINK_DEST_OPTION=""
|
LINK_DEST_OPTION=""
|
||||||
@@ -157,28 +156,29 @@ while : ; do
|
|||||||
# Purge certain old backups before beginning new backup.
|
# Purge certain old backups before beginning new backup.
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
# Default value for $prev ensures that the most recent backup is never deleted.
|
# Default value for $PREV ensures that the most recent backup is never deleted.
|
||||||
prev="0000-00-00-000000"
|
PREV="0000-00-00-000000"
|
||||||
for fname in $(fn_find_backups); do
|
for FILENAME in $(fn_find_backups | sort -r); do
|
||||||
date=$(basename "$fname")
|
BACKUP_DATE=$(basename "$FILENAME")
|
||||||
stamp=$(fn_parse_date $date)
|
TIMESTAMP=$(fn_parse_date $BACKUP_DATE)
|
||||||
|
|
||||||
# Skip if failed to parse date...
|
# Skip if failed to parse date...
|
||||||
[ -n "$stamp" ] || continue
|
if [ -z "$TIMESTAMP" ]; then
|
||||||
|
fn_log_warn "Could not parse date: $FILENAME"
|
||||||
if [ $stamp -ge $KEEP_ALL_DATE ]; then
|
continue
|
||||||
: # Don't expire any backups in this range
|
|
||||||
|
|
||||||
elif [ $stamp -ge $KEEP_DAILIES_DATE ]; then
|
|
||||||
# Delete all but the most recent of each day.
|
|
||||||
[ "${date:0:10}" == "${prev:0:10}" ] && fn_expire_backup "$fname"
|
|
||||||
|
|
||||||
else
|
|
||||||
# Delete all but the most recent of each month.
|
|
||||||
[ "${date:0:7}" == "${prev:0:7}" ] && fn_expire_backup "$fname"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
prev=$date
|
if [ $TIMESTAMP -ge $KEEP_ALL_DATE ]; then
|
||||||
|
true
|
||||||
|
elif [ $TIMESTAMP -ge $KEEP_DAILIES_DATE ]; then
|
||||||
|
# Delete all but the most recent of each day.
|
||||||
|
[ "${BACKUP_DATE:0:10}" == "${PREV:0:10}" ] && fn_expire_backup "$FILENAME"
|
||||||
|
else
|
||||||
|
# Delete all but the most recent of each month.
|
||||||
|
[ "${BACKUP_DATE:0:7}" == "${PREV:0:7}" ] && fn_expire_backup "$FILENAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
PREV=$BACKUP_DATE
|
||||||
done
|
done
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@@ -196,8 +196,6 @@ while : ; do
|
|||||||
CMD="$CMD --numeric-ids"
|
CMD="$CMD --numeric-ids"
|
||||||
CMD="$CMD --links"
|
CMD="$CMD --links"
|
||||||
CMD="$CMD --hard-links"
|
CMD="$CMD --hard-links"
|
||||||
CMD="$CMD --delete"
|
|
||||||
CMD="$CMD --delete-excluded"
|
|
||||||
CMD="$CMD --one-file-system"
|
CMD="$CMD --one-file-system"
|
||||||
CMD="$CMD --archive"
|
CMD="$CMD --archive"
|
||||||
CMD="$CMD --itemize-changes"
|
CMD="$CMD --itemize-changes"
|
||||||
@@ -234,16 +232,10 @@ while : ; do
|
|||||||
rm -- "$LOG_FILE"
|
rm -- "$LOG_FILE"
|
||||||
|
|
||||||
if [ "$NO_SPACE_LEFT" == "0" ]; then
|
if [ "$NO_SPACE_LEFT" == "0" ]; then
|
||||||
# TODO: -y flag
|
|
||||||
read -p "It looks like there is no space left on the destination. Delete old backup? (Y/n) " yn
|
|
||||||
case $yn in
|
|
||||||
[Nn]* ) exit 0;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
fn_log_warn "No space left on device - removing oldest backup and resuming."
|
fn_log_warn "No space left on device - removing oldest backup and resuming."
|
||||||
|
|
||||||
BACKUP_FOLDER_COUNT=$(fn_find_backups | wc -l)
|
BACKUP_FOLDER_COUNT=$(fn_find_backups | wc -l)
|
||||||
if [ "$BACKUP_FOLDER_COUNT" -lt "2" ]; then
|
if [[ "$BACKUP_FOLDER_COUNT" -lt "2" ]]; then
|
||||||
fn_log_error "No space left on device, and no old backup to delete."
|
fn_log_error "No space left on device, and no old backup to delete."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -272,7 +264,7 @@ while : ; do
|
|||||||
rm -rf -- "$DEST_FOLDER/latest"
|
rm -rf -- "$DEST_FOLDER/latest"
|
||||||
ln -vs -- "$NOW" "$DEST_FOLDER/latest"
|
ln -vs -- "$NOW" "$DEST_FOLDER/latest"
|
||||||
|
|
||||||
rm -- "$INPROGRESS_FILE"
|
rm -f -- "$INPROGRESS_FILE"
|
||||||
# TODO: grep for "^rsync error:.*$" in log
|
# TODO: grep for "^rsync error:.*$" in log
|
||||||
fn_log_info "Backup completed without errors."
|
fn_log_info "Backup completed without errors."
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user