#!/usr/bin/env bash # called before backup resticwrapper_pre_backup() { return; } # called after backup resticwrapper_post_backup() { return; } # usage usage() { USAGE=$(cat <'. EOF ) echo "$USAGE"; } set -e; # helper functions source_config() { local config=$1; local configFallback=$2; if [[ ! -f "$config" ]]; then if [[ ! -f "$configFallback" ]]; then echo "No config file specified and could not find default in '${configFallback}'!"; echo ""; usage; exit 1; else config=${configFallback}; fi fi set -a; source "${config}"; set +a; } apply_defaults() { [[ -z ${RESTICWRAPPER_BACKUP_PASSWORD} ]] && RESTICWRAPPER_BACKUP_PASSWORD=''; [[ -z ${RESTICWRAPPER_BACKUP_PASSWORD_FILE} ]] && RESTICWRAPPER_BACKUP_PASSWORD_FILE=''; [[ -z ${RESTICWRAPPER_BACKUP_PRUNE} ]] && RESTICWRAPPER_BACKUP_PRUNE=true; [[ -z ${RESTICWRAPPER_BACKUP_KEEP_IN_DAYS} ]] && RESTICWRAPPER_BACKUP_KEEP_IN_DAYS=60; [[ -z ${RESTICWRAPPER_BACKUP_CHECK} ]] && RESTICWRAPPER_BACKUP_CHECK=true; [[ -z ${RESTICWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS} ]] && RESTICWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS=604800; [[ -z ${RESTICWRAPPER_BACKUP_CHECK_FILE} ]] && RESTICWRAPPER_BACKUP_CHECK_FILE="$HOME/.resticwrapper-${RESTICWRAPPER_BACKUP_NAME}.check"; [[ -z ${RESTICWRAPPER_BACKUP_LOG} ]] && RESTICWRAPPER_BACKUP_LOG=true; [[ -z ${RESTICWRAPPER_BACKUP_LOG_PRUNE} ]] && RESTICWRAPPER_BACKUP_LOG_PRUNE=true; [[ -z ${RESTICWRAPPER_BACKUP_LOG_FILE} ]] && RESTICWRAPPER_BACKUP_LOG_FILE="$HOME/.resticwrapper-${RESTICWRAPPER_BACKUP_NAME}.log"; [[ -z ${RESTICWRAPPER_BACKUP_NOTIFY_VIA_MAIL} ]] && RESTICWRAPPER_BACKUP_NOTIFY_VIA_MAIL=false; [[ -z ${RESTICWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS} ]] && RESTICWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS=""; [[ -z ${RESTICWRAPPER_BACKUP_NOTIFY_UI} ]] && RESTICWRAPPER_BACKUP_NOTIFY_UI=false; [[ -z ${RESTIC_BINARY} ]] && RESTIC_BINARY=$(which restic); [[ -z ${RESTICWRAPPER_RESTIC_INIT_PARAMS} ]] && RESTICWRAPPER_RESTIC_INIT_PARAMS="init -r ${RESTIC_REPOSITORY}"; [[ -z ${RESTICWRAPPER_RESTIC_CREATE_PARAMS} ]] && RESTICWRAPPER_RESTIC_CREATE_PARAMS="backup --verbose"; [[ -z ${RESTICWRAPPER_RESTIC_CHECK_PARAMS} ]] && RESTICWRAPPER_RESTIC_CHECK_PARAMS="check"; [[ -z ${RESTICWRAPPER_RESTIC_PRUNE_PARAMS} ]] && RESTICWRAPPER_RESTIC_PRUNE_PARAMS="forget --prune --keep-within 0y0m${RESTICWRAPPER_BACKUP_KEEP_IN_DAYS}d0h"; [[ -z ${RESTICWRAPPER_RESTIC_LIST_PARAMS} ]] && RESTICWRAPPER_RESTIC_LIST_PARAMS="snapshots"; [[ -z ${RESTICWRAPPER_RESTIC_INFO_PARAMS} ]] && RESTICWRAPPER_RESTIC_INFO_PARAMS="stats"; } check_required() { if [[ -z ${RESTICWRAPPER_BACKUP_REPOSITORY} ]]; then echo "RESTICWRAPPER_BACKUP_REPOSITORY is required" exit 1; fi if [[ -z ${RESTICWRAPPER_BACKUP_NAME} ]]; then echo "RESTICWRAPPER_BACKUP_NAME is required" exit 1; fi type ${RESTIC_BINARY} >/dev/null 2>&1 || { echo >&2 "Require '${RESTIC_BINARY}' (binary) but it's not installed. Aborting."; exit 1; } } # define wrapper functions backup() { echo "Using ${RESTIC_BINARY} as binary"; resticwrapper_pre_backup; set -a; RESTIC_REPOSITORY="${RESTICWRAPPER_BACKUP_REPOSITORY}${RESTICWRAPPER_BACKUP_NAME}"; set +a; if [ ! -z "${RESTICWRAPPER_BACKUP_PASSWORD}" ]; then export RESTIC_PASSWORD=${RESTICWRAPPER_BACKUP_PASSWORD}; fi if [ ! -z "${RESTICWRAPPER_BACKUP_PASSWORD_FILE}" ]; then export RESTIC_PASSWORD_FILE=${RESTICWRAPPER_BACKUP_PASSWORD}; fi # init hint echo "Hint: If you haven't, you need to create the restic repository manually before first run if it doesn't exist:"; echo "${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_INIT_PARAMS} ${RESTICWRAPPER_BACKUP_REPOSITORY}${RESTICWRAPPER_BACKUP_NAME}"; # create ${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_CREATE_PARAMS} "${RESTICWRAPPER_BACKUP_FILES[@]}" # notify UI if [ "${RESTICWRAPPER_BACKUP_NOTIFY_UI}" = true ]; then notify-send "Started backup" ${RESTIC_REPOSITORY}; fi # check if [ "${RESTICWRAPPER_BACKUP_CHECK}" = true ]; then # use for first time creation doCheck=false if [ ! -f "${RESTICWRAPPER_BACKUP_CHECK_FILE}" ]; then touch ${RESTICWRAPPER_BACKUP_CHECK_FILE} doCheck=true fi # compare date lastMod=$(date -r ${RESTICWRAPPER_BACKUP_CHECK_FILE} +%s) age=$(($(date "+%s") - ${lastMod})) if [ "$age" -gt "${RESTICWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS}" ]; then doCheck=true fi if [ "$doCheck" = true ]; then ${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_CHECK_PARAMS}; touch ${RESTICWRAPPER_BACKUP_CHECK_FILE} fi fi # prune if [ "${RESTICWRAPPER_BACKUP_PRUNE}" = true ]; then ${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_PRUNE_PARAMS}; fi # log if [ "${RESTICWRAPPER_BACKUP_LOG}" = true ]; then if [ "${RESTICWRAPPER_BACKUP_LOG_PRUNE}" = true ] && [ -f "${RESTICWRAPPER_BACKUP_LOG_FILE}" ]; then rm ${RESTICWRAPPER_BACKUP_LOG_FILE}; fi touch ${RESTICWRAPPER_BACKUP_LOG_FILE}; ${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_LIST_PARAMS} >> ${RESTICWRAPPER_BACKUP_LOG_FILE}; echo "---" >> ${RESTICWRAPPER_BACKUP_LOG_FILE}; ${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_INFO_PARAMS} >> ${RESTICWRAPPER_BACKUP_LOG_FILE}; if [ "${RESTICWRAPPER_BACKUP_NOTIFY_VIA_MAIL}" = true ]; then local hostname=$(hostname) cat ${RESTICWRAPPER_BACKUP_LOG_FILE}|mailx -Ssendwait -s "[resticwrapper on ${hostname} for ${RESTICWRAPPER_BACKUP_NAME}]" ${RESTICWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS}; fi fi # notify UI if [ "${RESTICWRAPPER_BACKUP_NOTIFY_UI}" = true ]; then notify-send "Finished backup" ${RESTIC_REPOSITORY}; fi resticwrapper_post_backup; } # check requirements CONFIG_FILE="$1"; FALLBACK_CONFIG_FILE="${HOME}/.resticwrapper.conf"; source_config "${CONFIG_FILE}" "${FALLBACK_CONFIG_FILE}"; apply_defaults; check_required; COMMAND="backup" case "$COMMAND" in backup) backup; ;; *) echo "Unsupported command or no command given" >&2 usage; exit 1 ;; esac