Can now specify restic/rsync/rclone repo names in repofile.

Renamed various options in ~/.backup/config to DEF_*
Records historical results of backups in ~/.backup/stats
Added 'check' command to check for successful backups in the last 24 hours (uses new stats file)
Now requires 'bc' (for check command)
This commit is contained in:
Rob Pearce 2020-08-23 11:06:49 +10:00
parent cde65f6ff1
commit f7af0de9f5
1 changed files with 281 additions and 76 deletions

357
bare.sh
View File

@ -2,8 +2,9 @@
VALIDCOMMANDS="go ls init repos stats diff forget" VALIDCOMMANDS="go ls init repos stats diff forget"
RCFILE=${HOME}/.backup/config RCFILE=${HOME}/.backup/config
AUTHFILE=${HOME}/.backup/auth DEF_AUTHFILE=${HOME}/.backup/auth
REPOFILE=${HOME}/.backup/repos REPOFILE=${HOME}/.backup/repos
STATFILE=${HOME}/.backup/stats
LOGFILE=/var/log/backup.log LOGFILE=/var/log/backup.log
RESTIC=/usr/local/bin/restic RESTIC=/usr/local/bin/restic
@ -28,19 +29,33 @@ function log() {
echo "${now} <${mode}> $*" >>${LOG} echo "${now} <${mode}> $*" >>${LOG}
} }
function updatestats() {
local repo cmd stamp code
repo=$1
cmd=$2
code=$3
stamp=`date +%s`
if [[ -f $STATFILE ]]; then
sed -i "/${repo}:${cmd}/d" $STATFILE
fi
echo "${repo}:${cmd}:${code}:${stamp}" >> $STATFILE
}
function usage-repo() { function usage-repo() {
echo " reponame1:/path/to/files1/:tag1,tag2,...,tagX" echo " reponame1;/path/to/files1/;tag1,tag2,...,tagX;repo_url;repo_passfile;repo_excludefail"
echo " reponame2:/path/to/files2/:tag1,tag2,...,tagX" echo " reponame2;/path/to/files2/;tag1,tag2,...,tagX;repo_url;repo_passfile;repo_excludefail"
echo " ..." echo " ..."
echo " reponameX:/path/to/filesX/:tag1,tag2,...,tagX" echo " reponameX;/path/to/filesX/;tag1,tag2,...,tagX;repo_url;repo_passfile;repo_excludefail"
echo ""
echo " Default password file is: $DEF_AUTHFILE"
echo "" echo ""
echo "Backup method tags:" echo "Backup method tags:"
echo " restic Backup using restic to Backblaze B2 bucket \$B2_BUCKET_PREFIX-<reponame>" echo " restic Backup using restic (default repo is Backblaze B2 bucket \$B2_BUCKET_PREFIX-<reponame>)"
echo " rclone Backup using rclone to Backblaze B2 bucket \$B2_BUCKET_PREFIX-<reponame>" echo " rclone Backup using rclone (default repo is Backblaze B2 bucket \$B2_BUCKET_PREFIX-<reponame>)"
echo " rsync Backup using rsync to \$RSYNC_USER@\$RSYNC_SERVER:\$RSYNC_DIR/<reponame>." echo " rsync Backup using rsync (defualt repo is \$DEF_RSYNC_USER@\$DEF_RSYNC_SERVER:\$DEF_RSYNC_DIR/<reponame>)"
echo "" echo ""
echo "Pre-backup commands to access local files:" echo "Pre-backup commands to access local files:"
echo " nfs Mount \$NFS_SERVER:\$NFS_SERVER_BASE/<sharename> to <repopath>" echo " nfs Mount \$DEF_NFS_SERVER:\$DEF_NFS_SERVER_BASE/<sharename> to <repopath>"
echo " before running. Sharename determined by stripping \$NFS_PREFIX" echo " before running. Sharename determined by stripping \$NFS_PREFIX"
echo " from start of repo path." echo " from start of repo path."
echo " usmb Run 'usmb reponame' to mount \$USMB_PREFIX/<sharename> before running." echo " usmb Run 'usmb reponame' to mount \$USMB_PREFIX/<sharename> before running."
@ -53,18 +68,17 @@ function usage-rc() {
echo " export B2_APP_KEY=xxx # Backblaze B2 bucket auth" echo " export B2_APP_KEY=xxx # Backblaze B2 bucket auth"
echo " export B2_BUCKET_PREFIX=xxx # Prefix to append to create unique B2 bucket name" echo " export B2_BUCKET_PREFIX=xxx # Prefix to append to create unique B2 bucket name"
echo "" echo ""
echo " export RESTIC_PASSWORD=xxx # Password used to encrypt Restic backups"
echo " export RESTIC_KEEPDAYS=31 # Days to keep restic backups for" echo " export RESTIC_KEEPDAYS=31 # Days to keep restic backups for"
echo "" echo ""
echo " export RSYNC_SERVER=xxx # Server used for repos with 'rsync' tag" echo " export DEF_RSYNC_SERVER=xxx # Server used for repos with 'rsync' tag"
echo " export RSYNC_USER=backups # Username for rsync server" echo " export DEF_RSYNC_USER=backups # Username for rsync server"
echo " export RSYNC_DIR=/home/backups/backups # Remote directory on rsync server" echo " export DEF_RSYNC_DIR=/home/backups/backups # Remote directory on rsync server"
echo " export RSYNC_OPTIONS=-Pavz # Options to pass to rsync" echo " export RSYNC_OPTIONS=-Pavz # Options to pass to rsync"
echo "" echo ""
echo " export USMB_PREFIX=/DataVolume/shares # Strip this from repo path to get USMB share name" echo " export USMB_PREFIX=/DataVolume/shares # Strip this from repo path to get USMB share name"
echo "" echo ""
echo " export NFS_SERVER=nfs.yourdomain.com # NFS server where local files for 'nfs' repos are found" echo " export DEF_NFS_SERVER=nfs.yourdomain.com # NFS server where local files for 'nfs' repos are found"
echo " export NFS_SERVER_BASE=/remote/nfs/share/base # Path on local NFS server to prefix to repo names" echo " export DEF_NFS_SERVER_BASE=/remote/nfs/share/base # Path on local NFS server to prefix to repo names"
echo " export NFS_PREFIX=/local/nfs/mountpoint # Where to mount NFS exports locally before backing them up" echo " export NFS_PREFIX=/local/nfs/mountpoint # Where to mount NFS exports locally before backing them up"
} }
@ -94,15 +108,16 @@ function getdatapath() {
DATAPATH="" DATAPATH=""
for x in ${REPODEFS[@]}; do for x in ${REPODEFS[@]}; do
match="^${REPO}:" match="^${REPO}\;"
if [[ $x =~ $match ]]; then if [[ $x =~ $match ]]; then
DATAPATH=`echo $x | sed -e s/${match}//` DATAPATH=`echo $x | sed -e s/${match}//`
fi fi
done done
DATAPATH=`echo $DATAPATH | sed -e s/:.*//` DATAPATH=`echo $DATAPATH | sed -e s/\;.*//`
echo "$DATAPATH" echo "$DATAPATH"
} }
function getmode() { function getmode() {
local mode
checktag "$1" rclone checktag "$1" rclone
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
mode=rclone mode=rclone
@ -114,28 +129,114 @@ function getmode() {
mode=restic mode=restic
fi fi
fi fi
echo "$mode"
} }
function checktag() { # return 0 if tag matches function getrepoexcludefile() { # output path
local reponame lookfor x match repodef local res rv
reponame="$1" res=`getrepotok $1 7`
lookfor="$2" rv=$?
echo "$res"
return $rv
}
# if we were just given a repo name, look up the def function getrepopath() { # output path
if [[ $reponame =~ ^.*:.*$ ]]; then local res rv mode def repobase
res=`getrepotok $1 4`
rv=$?
if [[ -z $res ]]; then
mode=`getmode $1`
repobase=`getreponame $1`
if [[ $mode == "restic" ]]; then
def="b2:${B2_BUCKET_PREFIX}-${repobase}"
elif [[ $mode == "rclone" ]]; then
def="remote:${B2_BUCKET_PREFIX}-${repobase}"
elif [[ $mode == "rsync" ]]; then
def="${DEF_RSYNC_USER}@${DEF_RSYNC_SERVER}:${DEF_RSYNC_DIR}/$repobase"
else
def="(no default repo for mode $mode)"
fi
res="$def"
fi
echo "$res"
return $rv
}
function getrepopassfile() { # output path
local res rv
res=`getrepotok $1 5`
rv=$?
echo "$res"
return $rv
}
function getrepotags() { # output path
local res rv
res=`getrepotok $1 3`
rv=$?
echo "$res"
return $rv
}
function getrepotok() { # output given token from repo def
local def res rv code idx
def=`getrepodef "$1"`
idx=$2
code="{ print \$${idx} }"
res=`echo "$def" | awk -F';' "$code"`
echo "$res"
if [[ -z $res ]]; then
rv=1
else
rv=0
fi
return $rv
}
function getreponame() {
local reponame
reponame="$1"
if [[ $reponame =~ ^.*\;.*$ ]]; then
# if we were given a repo def, return just the name
reponame=`echo "$reponame" | sed -e 's/\;.*//g'`
fi
echo "$reponame"
}
function getrepodef() {
local reponame match repodef x
reponame="$1"
if [[ $reponame =~ ^.*\;.*$ ]]; then
repodef="$reponame" repodef="$reponame"
else else
# if we were just given a repo name, look up the def
repodef="" repodef=""
for x in ${REPODEFS[@]}; do for x in ${REPODEFS[@]}; do
match="^${reponame}:" match="^${reponame};"
if [[ $x =~ $match ]]; then if [[ $x =~ $match ]]; then
repodef="$x" repodef="$x"
fi fi
done done
fi fi
echo "$repodef"
}
if [[ $repodef =~ ^.*:.*:.*${lookfor}.*$ ]]; then function checktag() { # return 0 if tag matches
local reponame lookfor justtags
reponame="$1"
lookfor="$2"
justtags=`getrepotags "$reponame"`
if [[ $justtags =~ ^.*${lookfor}.*$ ]]; then
return 0 return 0
fi fi
return 1 return 1
@ -196,18 +297,15 @@ if ! [ -e ${REPOFILE} ]; then
usage-repo usage-repo
exit 1 exit 1
fi fi
which bc >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error - can't find bc in path"
echo ""
exit 1
fi
. ${RCFILE} . ${RCFILE}
if [[ -z $B2_APP_ID ]]; then
echo "Error - \$B2_APP_ID not set."
exit 1
fi
if [[ -z $B2_APP_KEY ]]; then
echo "Error - \$B2_APP_KEY not set."
exit 1
fi
if [[ -z $RESTIC_KEEPDAYS ]]; then if [[ -z $RESTIC_KEEPDAYS ]]; then
echo "Error - \$RESTIC_KEEPDAYS not set." echo "Error - \$RESTIC_KEEPDAYS not set."
exit 1 exit 1
@ -225,10 +323,26 @@ fi
idx=0 idx=0
for f in `cat $REPOFILE`; do for f in `cat $REPOFILE`; do
REPODEFS[$idx]="$f" REPODEFS[$idx]="$f"
mode=`getmode "$f"`
if [[ $mode == "restic" ]]; then
thisrpath=`getrepopath $f`
if [[ ${thisrpath,,} == *b2* ]]; then
if [[ -z $B2_APP_ID ]]; then
echo "Error - \$B2_APP_ID not set."
exit 1
fi
if [[ -z $B2_APP_KEY ]]; then
echo "Error - \$B2_APP_KEY not set."
exit 1
fi
fi
fi
if [[ $DOALL -eq 1 ]]; then if [[ $DOALL -eq 1 ]]; then
checktag "$f" auto checktag "$f" auto
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
REPOSTOBACKUP="$REPOSTOBACKUP `echo $f | sed -e 's/:.*//'`" REPOSTOBACKUP="$REPOSTOBACKUP `echo $f | sed -e 's/\;.*//'`"
fi fi
fi fi
idx=$((idx + 1)) idx=$((idx + 1))
@ -247,13 +361,13 @@ if [[ -z $REPOSTOBACKUP ]]; then
fi fi
if [[ $CMD == "repos" ]]; then if [[ $CMD == "repos" ]]; then
format="%-20s%-40s%-10s\n" format="%-10s%-20s%-20s%s\n"
echo "Repos defined in ${RCFILE}:" echo "Repos defined in ${RCFILE}:"
echo "" echo ""
printf "$format" "Repo" "Path" "Tags" printf "$format" "Repo" "Path" "Tags" "Repo path"
for x in ${REPODEFS[@]}; do for x in ${REPODEFS[@]}; do
IFS=':' read -ra tok <<< "$x" IFS=';' read -ra tok <<< "$x"
thisrepo=${tok[0]} thisrepo=${tok[0]}
thispath=${tok[1]} thispath=${tok[1]}
if [[ -z ${tok[2]} ]]; then if [[ -z ${tok[2]} ]]; then
@ -261,8 +375,10 @@ if [[ $CMD == "repos" ]]; then
else else
tags=`echo "${tok[2]}" | sed -e 's/,/ /g'` tags=`echo "${tok[2]}" | sed -e 's/,/ /g'`
fi fi
thisrpath=`getrepopath $thisrepo`
[[ -z $thisrpath ]] && thisrpath="(default)"
printf "$format" "$thisrepo" "$thispath" "$tags" printf "$format" "$thisrepo" "$thispath" "$tags" "$thisrpath"
done done
exit 0 exit 0
fi fi
@ -275,8 +391,9 @@ fi
# Validate repos # Validate repos
GOODREPOS="" GOODREPOS=""
for f in $REPOSTOBACKUP; do for f in $REPOSTOBACKUP; do
REPO=${f}
DATAPATH=$(getdatapath $f) DATAPATH=$(getdatapath $f)
getmode "$f" mode=`getmode "$REPO"`
checktag "$f" usmb checktag "$f" usmb
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
@ -284,7 +401,7 @@ for f in $REPOSTOBACKUP; do
USMBNAME=$f USMBNAME=$f
else else
if ! [[ $DATAPATH == *${USMB_PREFIX}* ]]; then if ! [[ $DATAPATH == *${USMB_PREFIX}* ]]; then
log "Error: path '$DATAPATH' of repo '$REPO' does not contain '$USMB_PREFIX'." log "Error: path '$DATAPATH' of repo '$REPO' does not contain smb prefix '$USMB_PREFIX'."
continue continue
fi fi
USMBNAME=`echo "${DATAPATH}" | sed -e "s,${USMB_PREFIX}/\(.*\).*,\1,"` USMBNAME=`echo "${DATAPATH}" | sed -e "s,${USMB_PREFIX}/\(.*\).*,\1,"`
@ -297,20 +414,20 @@ for f in $REPOSTOBACKUP; do
checktag "$f" nfs checktag "$f" nfs
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
if [[ -z $NFS_SERVER ]]; then if [[ -z $DEF_NFS_SERVER ]]; then
log "Error: repo '$REPO' has nfs tag but \$NFS_SERVER not defined." log "Error: repo '$REPO' has nfs tag but \$DEF_NFS_SERVER not defined."
continue continue
fi fi
if [[ -z $NFS_SERVER_BASE ]]; then if [[ -z $DEF_NFS_SERVER_BASE ]]; then
log "Error: repo '$REPO' has nfs tag but \$NFS_SERVER_BASE not defined." log "Error: repo '$REPO' has nfs tag but \$DEF_NFS_SERVER_BASE not defined."
continue continue
fi fi
if ! [[ $DATAPATH == *${NFS_PREFIX}* ]]; then if ! [[ $DATAPATH == *${NFS_PREFIX}* ]]; then
log "Error: path '$DATAPATH' of repo '$REPO' does not contain '$NFS_PREFIX'." log "Error: path '$DATAPATH' of repo '$REPO' does not contain nfs prefix '$NFS_PREFIX'."
continue continue
fi fi
NFSNAME=`echo "${DATAPATH}" | sed -e "s,${NFS_PREFIX}/\(.*\).*,\1,"` NFSNAME=`echo "${DATAPATH}" | sed -e "s,${NFS_PREFIX}/\(.*\).*,\1,"`
NFSPATH="${NFS_SERVER}:${NFS_SERVER_BASE}/${NFSNAME}" NFSPATH="${DEF_NFS_SERVER}:${DEF_NFS_SERVER_BASE}/${NFSNAME}"
USENFS=1 USENFS=1
else else
NFSNAME="" NFSNAME=""
@ -395,6 +512,8 @@ if [[ $TESTMODE -eq 1 ]]; then
exit 0 exit 0
fi fi
errcount=0 # used for 'check' mode
warncount=0 # used for 'check' mode
for f in $REPOSTOBACKUP; do for f in $REPOSTOBACKUP; do
REPO=${f} REPO=${f}
DATAPATH=$(getdatapath $REPO) DATAPATH=$(getdatapath $REPO)
@ -414,16 +533,20 @@ for f in $REPOSTOBACKUP; do
checktag "$f" nfs checktag "$f" nfs
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
NFSNAME=`echo "${DATAPATH}" | sed -e "s,${NFS_PREFIX}/\(.*\).*,\1,"` NFSNAME=`echo "${DATAPATH}" | sed -e "s,${NFS_PREFIX}/\(.*\).*,\1,"`
NFSPATH="${NFS_SERVER}:${NFS_SERVER_BASE}/${NFSNAME}" NFSPATH="${DEF_NFS_SERVER}:${DEF_NFS_SERVER_BASE}/${NFSNAME}"
USENFS=1 USENFS=1
else else
NFSNAME="" NFSNAME=""
USENFS=0 USENFS=0
fi fi
export RESTIC_REPOSITORY="b2:${B2_BUCKET_PREFIX}-${REPO}"
export RCLONE_REPOSITORY="remote:${B2_BUCKET_PREFIX}-${REPO}"
export RSYNC_FULLDIR="${RSYNC_DIR}/${REPO}" export REPO_PATH=`getrepopath "$f"`
export RSYNC_REPOSITORY="${RSYNC_USER}@${RSYNC_SERVER}:${RSYNC_FULLDIR}" if [[ $? -eq 0 ]]; then
USINGDEFAULT=0
else
USINGDEFAULT=1
fi
if [[ $CMD == "go" ]]; then if [[ $CMD == "go" ]]; then
NEEDMOUNT=1 NEEDMOUNT=1
@ -434,10 +557,22 @@ for f in $REPOSTOBACKUP; do
fi fi
getmode "$f" mode=`getmode "$f"`
SPEEDOPTS=""
AUTHOPTS=""
OTHEROPTS=""
CONNECTIONOPTS=""
if [[ $mode == "restic" ]]; then if [[ $mode == "restic" ]]; then
MYREPO="restic: $RESTIC_REPOSITORY" MYREPO="restic: $REPO_PATH"
export RESTIC_REPOSITORY="$REPO_PATH"
export RESTIC_PASSWORD_FILE=`getrepopassfile "$f"`
if [[ ! -z $RESTIC_PASSWORD_FILE ]]; then
unset RESTIC_PASSWORD
AUTHOPTS="-p ${RESTIC_PASSWORD_FILE}"
else
AUTHOPTS="-p ${DEF_AUTHFILE}"
fi
if [[ -z $KSPEED ]]; then if [[ -z $KSPEED ]]; then
SPEEDOPTS="" SPEEDOPTS=""
else else
@ -450,11 +585,22 @@ for f in $REPOSTOBACKUP; do
CONNECTIONSOPTS="-o b2.connections=${CONNECTIONS}" CONNECTIONSOPTS="-o b2.connections=${CONNECTIONS}"
fi fi
AUTHOPTS="-p ${AUTHFILE}" export RESTIC_EXCLUDEFILE=`getrepoexcludefile "$f"`
if [[ ! -z $RESTIC_PASSWORD_FILE ]]; then
OTHEROPTS="$OTHEROPTS -exclude-file=${RESTIC_EXCLUDE}"
fi
elif [[ $mode == "rsync" ]]; then elif [[ $mode == "rsync" ]]; then
# rsync # rsync
MYREPO="rsync: ${RSYNC_USER}@${RSYNC_SERVER}:${RSYNC_FULLDIR}" MYREPO="rsync: $REPO_PATH"
for f in RSYNC_SERVER RSYNC_USER RSYNC_DIR RSYNC_OPTIONS ]]; do export RSYNC_REPOSITORY="$REPO_PATH"
export RSYNC_FULLDIR="${DEF_RSYNC_DIR}/${REPO}"
if [[ $USINGDEFAULT -eq 1 ]]; then
list="DEF_RSYNC_SERVER DEF_RSYNC_USER DEF_RSYNC_DIR RSYNC_OPTIONS"
else
list="RSYNC_OPTIONS"
fi
for f in $list; do
eval val='$'$f eval val='$'$f
if [[ -z $val ]]; then if [[ -z $val ]]; then
echo "Error - \$$f not set. Please update ${RCFILE}." echo "Error - \$$f not set. Please update ${RCFILE}."
@ -472,7 +618,8 @@ for f in $REPOSTOBACKUP; do
CONNECTIONSOPTS="" CONNECTIONSOPTS=""
else else
# rclone # rclone
MYREPO="rclone: $RCLONE_REPOSITORY" MYREPO="rclone: $REPO_PATH"
export RCLONE_REPOSITORY="$REPO_PATH"
if [[ -z $KSPEED ]]; then if [[ -z $KSPEED ]]; then
SPEEDOPTS="" SPEEDOPTS=""
else else
@ -487,15 +634,50 @@ for f in $REPOSTOBACKUP; do
fi fi
text="Starting '$CMD' on repo '$REPO' [$DATAPATH <-> $MYREPO]" if [[ ! $CMD == "check" ]]; then
log "$text" text="Starting '$CMD' on repo '$REPO' [$DATAPATH <-> $MYREPO]"
log "$text"
if [[ $mode == "restic" ]]; then fi
if [[ $CMD == "check" ]]; then
line=`egrep "^$REPO:go:" $STATFILE 2>/dev/null`
if [[ $? -eq 0 ]]; then
# Get result
code=`echo "$line" | cut -d: -f3`
stamp=`echo "$line" | cut -d: -f4`
date --version 2>&1 | grep -q GNU
if [[ $? -eq 0 ]]; then
humanstamp=`date --date="@$stamp"`
else
humanstamp=`date -r $stamp`
fi
now=`date +%s`
age=$( echo "$now - $stamp" | bc )
oneday=$( echo "24 * 60 * 60" | bc)
if [[ $code -eq 0 ]]; then
if [[ $age -le $oneday ]]; then
echo "OK: Last backup for '$REPO' succeeded on $humanstamp."
rv=0
else
echo "CRITICAL: Last backup for '$REPO' succeeded on $humanstamp (not in last 24 hours)."
errcount=$(( $errcount + 1))
rv=2
fi
else
echo "CRITICAL: Last backup for '$REPO' failed on $humanstamp."
rv=2
errcount=$(( $errcount + 1))
fi
else
echo "WARNING: No history found for repo '$REPO'"
rv=1
warncount=$(( $warncount + 1))
fi
elif [[ $mode == "restic" ]]; then
if [[ $CMD == "go" ]]; then if [[ $CMD == "go" ]]; then
if [[ $CRONMODE -eq 1 ]]; then if [[ $CRONMODE -eq 1 ]]; then
${RESTIC} backup $AUTHOPTS $CONNECTIONSOPTS $SPEEDOPTS $DATAPATH 2>&1 | egrep "^(Added|processed|snapshot)" >> ${LOG} ${RESTIC} backup $AUTHOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $DATAPATH 2>&1 | egrep "^(Added|processed|snapshot)" >> ${LOG}
else else
${RESTIC} backup $AUTHOPTS $CONNECTIONSOPTS $SPEEDOPTS $DATAPATH 2>&1 >> ${LOG} ${RESTIC} backup $AUTHOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $DATAPATH 2>&1 >> ${LOG}
fi fi
rv=$? rv=$?
elif [[ $CMD == "ls" ]]; then elif [[ $CMD == "ls" ]]; then
@ -512,17 +694,20 @@ for f in $REPOSTOBACKUP; do
${RESTIC} stats $AUTHOPTS $CONNECTIONSOPTS >/dev/null 2>&1 ${RESTIC} stats $AUTHOPTS $CONNECTIONSOPTS >/dev/null 2>&1
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
log "ERROR: Repo ${REPO} already exists. Aborting." log "ERROR: Repo ${REPO} already exists. Aborting."
rv=1
else else
${RESTIC} init $AUTHOPTS $CONNECTIONSOPTS >/dev/null 2>&1 ${RESTIC} init $AUTHOPTS $CONNECTIONSOPTS >/dev/null 2>&1
rv=$?
fi fi
elif [[ $CMD == "forget" ]]; then elif [[ $CMD == "forget" ]]; then
# age out stuff after RESTIC_KEEPDAYS days # age out stuff after RESTIC_KEEPDAYS days
FORGETOPTS="-d ${RESTIC_KEEPDAYS}" FORGETOPTS="-d ${RESTIC_KEEPDAYS}"
${RESTIC} forget $AUTHOPTS $CONNECTIONSOPTS $FORGETOPTS 2>&1 | awk '($1 == "Applying") { print } ($2 == "snapshots") { show=0 } (show == 1 && $1 != "ID" && NF > 1) { print "Removing: " $0 } ($1 == "remove") { show=1 }' >> ${LOG} ${RESTIC} forget $AUTHOPTS $CONNECTIONSOPTS $FORGETOPTS 2>&1 | awk '($1 == "Applying") { print } ($2 == "snapshots") { show=0 } (show == 1 && $1 != "ID" && NF > 1) { print "Removing: " $0 } ($1 == "remove") { show=1 }' >> ${LOG}
rv=$?
${RESTIC} prune $AUTHOPTS 2>&1 | egrep "^(repository contain|found|will|remove)" >> ${LOG} ${RESTIC} prune $AUTHOPTS 2>&1 | egrep "^(repository contain|found|will|remove)" >> ${LOG}
else else
log "Error: invalid command $CMD" log "Error: invalid command $CMD"
rv=0 rv=1
fi fi
elif [[ $mode == "rsync" ]]; then elif [[ $mode == "rsync" ]]; then
REMOTE="" REMOTE=""
@ -532,22 +717,22 @@ for f in $REPOSTOBACKUP; do
${RSYNC} ${RSYNC_OPTIONS} $DATAPATH/ ${RSYNC_REPOSITORY} 2>&1 >> ${LOG} ${RSYNC} ${RSYNC_OPTIONS} $DATAPATH/ ${RSYNC_REPOSITORY} 2>&1 >> ${LOG}
rv=$? rv=$?
elif [[ $CMD == "ls" ]]; then elif [[ $CMD == "ls" ]]; then
ssh ${RSYNC_USER}@${RSYNC_SERVER} ls ${RSYNC_FULLDIR} 2>&1 >> ${LOG} ssh ${DEF_RSYNC_USER}@${DEF_RSYNC_SERVER} ls ${RSYNC_FULLDIR} 2>&1 >> ${LOG}
rv=$? rv=$?
elif [[ $CMD == "stats" ]]; then elif [[ $CMD == "stats" ]]; then
echo "Size of remote data for ${REPO}:" echo "Size of remote data for ${REPO}:"
ssh ${RSYNC_USER}@${RSYNC_SERVER} du -hs ${RSYNC_FULLDIR} 2>&1 >> ${LOG} ssh ${DEF_RSYNC_USER}@${DEF_RSYNC_SERVER} du -hs ${RSYNC_FULLDIR} 2>&1 >> ${LOG}
rv=$? rv=$?
elif [[ $CMD == "diff" ]]; then elif [[ $CMD == "diff" ]]; then
${RSYNC} ${RSYNC_OPTIONS} -n $DATAPATH/ ${RSYNC_REPOSITORY} 2>&1 >> ${LOG} ${RSYNC} ${RSYNC_OPTIONS} -n $DATAPATH/ ${RSYNC_REPOSITORY} 2>&1 >> ${LOG}
rv=$? rv=$?
elif [[ $CMD == "init" ]]; then elif [[ $CMD == "init" ]]; then
# check whether it already exists first! # check whether it already exists first!
ssh ${RSYNC_USER}@${RSYNC_SERVER} ls -d ${RSYNC_FULLDIR} 2>&1 >> ${LOG} ssh ${DEF_RSYNC_USER}@${DEF_RSYNC_SERVER} ls -d ${RSYNC_FULLDIR} 2>&1 >> ${LOG}
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
log "ERROR: Repo ${REPO} already exists. Aborting." log "ERROR: Repo ${REPO} already exists. Aborting."
else else
ssh ${RSYNC_USER}@${RSYNC_SERVER} mkdir -p ${RSYNC_FULLDIR} 2>&1 >>${LOG} ssh ${DEF_RSYNC_USER}@${DEF_RSYNC_SERVER} mkdir -p ${RSYNC_FULLDIR} 2>&1 >>${LOG}
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
log "Created directory ${RSYNC_FULLDIR}..." log "Created directory ${RSYNC_FULLDIR}..."
else else
@ -556,24 +741,25 @@ for f in $REPOSTOBACKUP; do
fi fi
elif [[ $CMD == "forget" ]]; then elif [[ $CMD == "forget" ]]; then
log "Error: forget not supported for rsync mode." log "Error: forget not supported for rsync mode."
rv=1
else else
log "Error: invalid command $CMD" log "Error: invalid command $CMD"
rv=0 rv=1
fi fi
else else
# rclone # rclone
REMOTE="" REMOTE=""
if [[ $CMD == "go" ]]; then if [[ $CMD == "go" ]]; then
${RCLONE} sync $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $DATAPATH $RCLONE_REPOSITORY 2>&1 >> ${LOG} ${RCLONE} sync $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $DATAPATH $RCLONE_REPOSITORY 2>&1 >> ${LOG}
rv=$? rv=$?
elif [[ $CMD == "ls" ]]; then elif [[ $CMD == "ls" ]]; then
${RCLONE} ls $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $RCLONE_REPOSITORY 2>&1 >> ${LOG} ${RCLONE} ls $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $RCLONE_REPOSITORY 2>&1 >> ${LOG}
rv=$? rv=$?
elif [[ $CMD == "stats" ]]; then elif [[ $CMD == "stats" ]]; then
${RCLONE} size $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $RCLONE_REPOSITORY 2>&1 >> ${LOG} ${RCLONE} size $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $RCLONE_REPOSITORY 2>&1 >> ${LOG}
rv=$? rv=$?
elif [[ $CMD == "diff" ]]; then elif [[ $CMD == "diff" ]]; then
${RCLONE} check $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $RCLONE_REPOSITORY 2>&1 >> ${LOG} ${RCLONE} check $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $RCLONE_REPOSITORY 2>&1 >> ${LOG}
rv=$? rv=$?
elif [[ $CMD == "init" ]]; then elif [[ $CMD == "init" ]]; then
# check whether it already exists first! # check whether it already exists first!
@ -606,19 +792,38 @@ for f in $REPOSTOBACKUP; do
fi fi
elif [[ $CMD == "forget" ]]; then elif [[ $CMD == "forget" ]]; then
log "Error: forget not supported for rclone mode." log "Error: forget not supported for rclone mode."
rv=1
else else
log "Error: invalid command $CMD" log "Error: invalid command $CMD"
rv=0 rv=1
fi fi
fi fi
if [[ ! $CMD == "check" ]]; then
# Record result
updatestats $f $CMD $rv
fi
if [[ $rv -eq 0 ]]; then if [[ $rv -eq 0 ]]; then
if [[ $NEEDMOUNT -eq 1 ]]; then if [[ $NEEDMOUNT -eq 1 ]]; then
do_umount do_umount
fi fi
else elif [[ ! $CMD == "check" ]]; then
log "Error: '$CMD' on repo '$REPO' failed" log "Error: '$CMD' on repo '$REPO' failed"
fi fi
log "Finished '$CMD' on repo '$REPO'" if [[ ! $CMD == "check" ]]; then
log "Finished '$CMD' on repo '$REPO'"
fi
done done
if [[ $CMD == "check" ]]; then
if [[ $errcount -ge 1 ]]; then
rv=2
elif [[ $warncount -ge 1 ]]; then
rv=1
else
rv=0
fi
exit $rv
fi