2 files changed, 119 insertions(+), 17 deletions(-)
A crontab
M system-backup -rw-r--r-- => -rwxr-xr-x
A crontab => crontab +5 -0
@@ 0,0 1,5 @@
+# Run the hourly jobs
+SHELL=/bin/bash
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+MAILTO=root
+01 * * * * root system-backup -q
M system-backup => system-backup +114 -17
@@ 1,26 1,123 @@
#!/bin/bash
-source /etc/backup/config || exit 1
+CONFIG_DIR="/etc/backup"
+STATE_FILE="/var/spool/backup/default"
-if [ "x$BORG_REPO" = "x" ]; then
- echo "BORG_REPO is unset, aborting. Please check /etc/backup/config."
- exit 2
-fi
+print_usage() {
+ echo "Usage: $0 [-Wfnpq] [-C path] [-S path]"
+ echo " $0 -h"
+ echo
+ echo "Starts a system backup."
+ echo
+ echo " -C path set path to config directory (default: ${CONFIG_DIR})"
+ echo " -S path set path to state file (default: ${STATE_FILE})"
+ echo " -W do not write state"
+ echo " -f force run backup even if already successfully run today"
+ echo " -h print this help text"
+ echo " -n dry run, do not actually run the backup"
+ echo " -p show backup progress"
+ echo " -q do not print as many status messages"
+ exit
+}
-export BORG_REPO
-export BORG_PASSPHRASE
+try_backup() {
+ today="$(date +%Y%m%d)"
-run-parts /etc/backup/before.d
+ mkdir -p "$(dirname "${STATE_FILE}")" || exit 1
-date="$(date '+%Y%m%d-%H%M%S')"
+ if [[ -f "${STATE_FILE}" ]]; then
+ last="$(cat "${STATE_FILE}")"
+ if [[ "$force" -eq 0 && "$last" -ge "$today" ]]; then
+ test $quiet -eq 0 && echo 'skipping backup; already ran today'
+ exit 4
+ fi
+ fi
-borg create -xvs \
- --exclude-caches \
- --exclude-if-present .nobackup --keep-exclude-tags \
- --exclude-from /etc/backup/excludes \
- "${BORG_OPTS[@]}" \
- "::$date" "${DIRS[@]}"
+ do_backup
+}
-export BACKUP_STATUS=$?
+do_backup() {
+ source "${CONFIG_DIR}"/config || exit 1
-run-parts /etc/backup/after.d
+ if [[ "x$BORG_REPO" = "x" ]]; then
+ echo "BORG_REPO is unset, aborting. Please check /etc/backup/config."
+ exit 2
+ fi
+
+ if [[ "$dry_run" -ne 0 ]]; then
+ test $quiet -eq 0 && echo 'skipping backup because -n was specified'
+ exit 0
+ fi
+
+ export BORG_REPO
+ export BORG_PASSPHRASE
+
+ run-parts -v "${CONFIG_DIR}"/before.d
+
+ if [[ $? -eq 0 ]]; then
+ date="$(date '+%Y%m%d-%H%M%S')"
+
+ borg create -xvs ${borg_opts_internal} \
+ --exclude-caches \
+ --exclude-if-present .nobackup --keep-exclude-tags \
+ --exclude-from "${CONFIG_DIR}"/excludes \
+ "${BORG_OPTS[@]}" \
+ "::$date" "${DIRS[@]}"
+
+ export BACKUP_STATUS=$?
+
+ if [[ "$no_write" -eq 0 && "$BACKUP_STATUS" -eq 0 ]]; then
+ echo "$today" > "${STATE_FILE}"
+ fi
+ fi
+
+ run-parts -v "${CONFIG_DIR}"/after.d
+
+ if [[ $? -ne 0 ]]; then
+ error=$?
+ else
+ error=$BACKUP_STATUS
+ fi
+
+ exit $BACKUP_STATUS
+}
+
+dry_run=0
+force=0
+quiet=0
+no_write=0
+borg_opts_internal=""
+
+while getopts 'C:S:Wfhnpq' arg; do
+ case ${arg} in
+ C)
+ CONFIG_DIR="${OPTARG}"
+ ;;
+ S)
+ STATE_FILE="${OPTARG}"
+ ;;
+ W)
+ no_write=1
+ ;;
+ f)
+ force=1
+ ;;
+ h)
+ print_usage
+ ;;
+ n)
+ dry_run=1
+ ;;
+ p)
+ borg_opts_internal="${borg_opts_internal} -p"
+ ;;
+ q)
+ quiet=1
+ ;;
+ *)
+ print_usage
+ ;;
+ esac
+done
+
+try_backup