~dblsaiko/backup-scripts

a0a7b114440fe473332d6b509e7aa34ae2229dee — 2xsaiko 3 years ago ee07e23 master
Update script with more options

- retry multiple times per day with cronjob if backup fails
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