#!/bin/bash statusfile="/var/tmp/backup.monitoring" logdir="/var/log/backup-client" lock="/tmp/backup-client-is-running" ssh_login="${username}@${server}" ssh_opts="-o IdentityFile=/etc/backup.priv -o StrictHostKeyChecking=accept-new -p ${port}" nodename="${node.name}" <%text> try="${1:-}" [[ -n "$DEBUG" ]] && set -x do_backup() { echo "==> starting backup for '$1'" # Compress level 1 is a good compromise between speed and cpu usage. rsync --compress-level=1 -aAP --numeric-ids --delete --relative \ --rsync-path="/usr/bin/rsync --fake-super" \ -e "ssh $ssh_opts" \ "$1" "$ssh_login":backups/ # Exit code 24 means some files have vanished during rsync. # I don't know why, but this is very common, apparently? exitcode=$? echo "==> backup for '$1' exited $exitcode" if [[ $exitcode != 0 ]] && [[ $exitcode != 24 ]] then rsync_errors+=" $1 ($exitcode)" fi } on_exit() { rmdir "$lock" echo "*** END BACKUP RUN $(date '+%F %T %z') ***" } prepare_and_cleanup_logdir() { # rsync logs tend to get very large. That's why we pipe them through # gzip when writing. Because we're running multiple tries, we cannot # rely on logrotate to rotate the logs, we have to do it ourselves. # Of course that means we have to clean up after ourselves, too. mkdir -p "$logdir" find "$logdir" -type f -mtime +14 -name "*.log" -delete find "$logdir" -type f -mtime +14 -name "*.gz" -delete } save_result_for_monitoring() { code=$1 msg=$2 printf "status=%q\n" "$code" > "$statusfile" printf "msg=%q\n" "$msg" >> "$statusfile" printf "timestamp=%q\n" "$(date +%s)" >> "$statusfile" } if ! mkdir "$lock" >/dev/null 2>&1 then save_result_for_monitoring 2 "could not get lock" exit 1 fi trap "on_exit" EXIT # redirect stdout and stderr to logfile prepare_and_cleanup_logdir logfile="$logdir/backup--$(date '+%F--%H-%M-%S')--$$.log.gz" echo "All log output will go to $logfile" | logger -it backup-client exec > >(gzip >"$logfile") exec 2>&1 # this is where the real work starts ts_begin=$(date +%s) echo "*** BEGIN BACKUP RUN $(date '+%F %T %z') ***" echo "This is attempt $try" echo "using ssh options [$ssh_opts]" echo "using ssh login [$ssh_login]" if ! [[ -f /etc/backup.priv ]] then save_result_for_monitoring 2 "/etc/backup.priv does not exist" exit 100 fi for i in /etc/backup-pre-hooks.d/* do [[ -x "$i" ]] || continue echo "Running pre-hook '$i'" if ! $i then save_result_for_monitoring 2 "pre-hook '$i' failed to run" exit 1 fi done rsync_errors="" % for path in sorted(paths): do_backup "${path}" % endfor <%text> if [[ -n "$rsync_errors" ]] then save_result_for_monitoring 2 "rsync failed:$rsync_errors" exit 1 fi ssh $ssh_opts $ssh_login "sudo /usr/local/bin/rotate-single-backup-client $nodename"