#!/bin/bash VALIDCOMMANDS="go ls init repos stats diff forget" RCFILE=${HOME}/.backup/config DEF_AUTHFILE=${HOME}/.backup/auth REPOFILE=${HOME}/.backup/repos STATFILE=${HOME}/.backup/stats LOGFILE=/var/log/backup.log RESTIC=/usr/local/bin/restic RCLONE=/usr/local/bin/rclone RSYNC=/usr/local/bin/rsync USMB=/usr/local/bin/usmb #RCLONEOPTS="--cache-chunk-no-memory --buffer-size=10M --progress" RCLONEOPTS="--progress --buffer-size 10M --cache-chunk-no-memory" SPEED="" CRONMODE=0 CONNECTIONS="" LOG=/dev/stdout DATE=/bin/date DOALL=0 REPOSTOBACKUP="" TESTMODE=0 VERBOSE=0 function log() { local now now=`${DATE} +%Y/%m/%d-%H:%M:%S` 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() { echo " reponame1;/path/to/files1/;tag1,tag2,...,tagX;repo_url;repo_passfile;repo_excludefile" echo " reponame2;/path/to/files2/;tag1,tag2,...,tagX;repo_url;repo_passfile;repo_excludefile" echo " ..." echo " reponameX;/path/to/filesX/;tag1,tag2,...,tagX;repo_url;repo_passfile;repo_excludefile" echo "" echo " Default password file is: $DEF_AUTHFILE" echo "" echo "Backup method tags:" echo " restic Backup using restic (default repo is Backblaze B2 bucket \$B2_BUCKET_PREFIX-)" echo " rclone Backup using rclone (default repo is Backblaze B2 bucket \$B2_BUCKET_PREFIX-)" echo " rsync Backup using rsync (defualt repo is \$DEF_RSYNC_USER@\$DEF_RSYNC_SERVER:\$DEF_RSYNC_DIR/)" echo "" echo "Pre-backup commands to access local files:" echo " nfs Mount \$DEF_NFS_SERVER:\$DEF_NFS_SERVER_BASE/ to " echo " before running. Sharename determined by stripping \$NFS_PREFIX" echo " from start of repo path." echo " usmb Run 'usmb reponame' to mount \$USMB_PREFIX/ before running." echo " Sharename determined by stripping \$NFS_PREFIX from start of ." echo " localmount Run 'mount reponame' to mount before running." } function usage-rc() { echo " export B2_ACCOUNT_ID=xxx # Backblaze B2 credentials" echo " export B2_ACCOUNT_KEY=xxx # Backblaze B2 credentials" echo " export B2_APP_ID=xxx # Backblaze B2 bucket details" 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 "" echo " export RESTIC_KEEPDAYS=31 # Days to keep restic backups for" echo " export RESTICOPTS=\"--one-file-system\" # Extra args to pass to restic" echo "" echo " export DEF_RSYNC_SERVER=xxx # Server used for repos with 'rsync' tag" echo " export DEF_RSYNC_USER=backups # Username for 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 "" echo " export USMB_PREFIX=/DataVolume/shares # Strip this from repo path to get USMB share name" echo "" echo " export DEF_NFS_SERVER=nfs.yourdomain.com # NFS server where local files for 'nfs' repos are found" 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" } function usage() { echo "usage: $0 command reponame" echo "" echo " -a Run on all repos defined as 'auto'" echo " -h Show this usage text" echo " -s num Limit speed to 'num' Mbps (default: unlimited)" echo " -x num Use 'num' simultaneous connections (default: 20)" echo " -c Cron mode - log to ${LOGFILE}" echo " -t Test mode - dump what would be done then exit." echo "" echo "Valid commands are:" echo " $VALIDCOMMANDS" echo "" echo "${RCFILE} should look like this:" usage-rc echo "" echo "${REPOFILE} should look like this:" usage-repo echo "" } function getdatapath() { local DATAPATH REPO x REPO="$1" DATAPATH="" for x in ${REPODEFS[@]}; do match="^${REPO}\;" if [[ $x =~ $match ]]; then DATAPATH=`echo $x | sed -e s/${match}//` fi done DATAPATH=`echo $DATAPATH | sed -e s/\;.*//` echo "$DATAPATH" } function getmode() { local mode checktag "$1" rclone if [[ $? -eq 0 ]]; then mode=rclone else checktag "$1" rsync if [[ $? -eq 0 ]]; then mode=rsync else mode=restic fi fi echo "$mode" } function getrepoexcludefile() { # output path local res rv res=`getrepotok $1 6` rv=$? echo "$res" return $rv } function getrepopath() { # output path 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" else # if we were just given a repo name, look up the def repodef="" for x in ${REPODEFS[@]}; do match="^${reponame};" if [[ $x =~ $match ]]; then repodef="$x" fi done fi echo "$repodef" } function checktag() { # return 0 if tag matches local reponame lookfor justtags reponame="$1" lookfor="$2" justtags=`getrepotags "$reponame"` if [[ $justtags =~ ^.*${lookfor}.*$ ]]; then return 0 fi return 1 } function do_umount() { if [[ $USEUSMB -eq 1 ]]; then log "Unmounting usmb volume '$USMBNAME'" usmb -u $USMBNAME elif [[ $USENFS -eq 1 ]]; then log "Unmounting nfs volume '$NFSPATH' from $DATAPATH" umount $DATAPATH elif [[ $USELOCALMOUNT -eq 1 ]]; then log "Unmounting dir $DATAPATH" umount $DATAPATH fi } # Handle args ARGS="acdhs:tvx:" while getopts "$ARGS" i; do case "$i" in a) DOALL=1 ;; h) usage; exit 1 ;; s) SPEED="$OPTARG"; ;; x) CONNECTIONS="$OPTARG"; ;; c) CRONMODE=1; LOG=${LOGFILE} ;; t) TESTMODE=1 ;; v) VERBOSE=1 ;; *) echo "ERROR: invalid argument: $i"; usage; ;; esac done shift $((OPTIND - 1)) if ! [ -e ${RCFILE} ]; then echo "Error - can't find ${RCFILE}" echo "" usage-rc exit 1 fi if ! [ -e ${REPOFILE} ]; then echo "Error - can't find ${REPOFILE}" echo "" usage-repo exit 1 fi which bc >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "Error - can't find bc in path" echo "" exit 1 fi . ${RCFILE} if [[ -z $RESTIC_KEEPDAYS ]]; then echo "Error - \$RESTIC_KEEPDAYS not set." exit 1 fi # Convert speed from Mbps to KBps if ! [[ -z $SPEED ]]; then KSPEED=$(echo "scale=2; $SPEED * 125" | bc) else KSPEED="" fi # Get list of defined repos idx=0 for f in `cat $REPOFILE`; do 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 checktag "$f" auto if [[ $? -eq 0 ]]; then REPOSTOBACKUP="$REPOSTOBACKUP `echo $f | sed -e 's/\;.*//'`" fi fi idx=$((idx + 1)) done if ! [[ $VALIDCOMMANDS == *"$CMD"* ]]; then echo "Error - invalid command $CMD. Should one of: $VALIDCOMMANDS" exit 1 fi CMD="$1" shift 1 if [[ -z $REPOSTOBACKUP ]]; then REPOSTOBACKUP="$*" fi if [[ $CMD == "repos" ]]; then format="%-10s%-20s%-20s%s\n" echo "Repos defined in ${RCFILE}:" echo "" printf "$format" "Repo" "Path" "Tags" "Repo path" for x in ${REPODEFS[@]}; do IFS=';' read -ra tok <<< "$x" thisrepo=${tok[0]} thispath=${tok[1]} if [[ -z ${tok[2]} ]]; then tags="n/a" else tags=`echo "${tok[2]}" | sed -e 's/,/ /g'` fi thisrpath=`getrepopath $thisrepo` [[ -z $thisrpath ]] && thisrpath="(default)" printf "$format" "$thisrepo" "$thispath" "$tags" "$thisrpath" done exit 0 fi if [[ -z $REPOSTOBACKUP ]]; then usage exit 1 fi # Validate repos GOODREPOS="" for f in $REPOSTOBACKUP; do REPO=${f} DATAPATH=$(getdatapath $f) mode=`getmode "$REPO"` checktag "$f" usmb if [[ $? -eq 0 ]]; then if [[ -z $USMB_PREFIX ]]; then USMBNAME=$f else if ! [[ $DATAPATH == *${USMB_PREFIX}* ]]; then log "Error: path '$DATAPATH' of repo '$REPO' does not contain smb prefix '$USMB_PREFIX'." continue fi USMBNAME=`echo "${DATAPATH}" | sed -e "s,${USMB_PREFIX}/\(.*\).*,\1,"` fi USEUSMB=1 else USMBNAME="" USEUSMB=0 fi checktag "$f" nfs if [[ $? -eq 0 ]]; then if [[ -z $DEF_NFS_SERVER ]]; then log "Error: repo '$REPO' has nfs tag but \$DEF_NFS_SERVER not defined." continue fi if [[ -z $DEF_NFS_SERVER_BASE ]]; then log "Error: repo '$REPO' has nfs tag but \$DEF_NFS_SERVER_BASE not defined." continue fi if ! [[ $DATAPATH == *${NFS_PREFIX}* ]]; then log "Error: path '$DATAPATH' of repo '$REPO' does not contain nfs prefix '$NFS_PREFIX'." continue fi NFSNAME=`echo "${DATAPATH}" | sed -e "s,${NFS_PREFIX}/\(.*\).*,\1,"` NFSPATH="${DEF_NFS_SERVER}:${DEF_NFS_SERVER_BASE}/${NFSNAME}" USENFS=1 else NFSNAME="" USENFS=0 fi checktag "$f" localmount if [[ $? -eq 0 ]]; then grep -q $DTAPATH /etc/fstab if [[ $? -ne 0 ]]; then log "Error: repo '$REPO' has localmount tag but $DATAPATH not in fstab." continue fi USELOCALMOUNT=1 else USELOCALMOUNT=0 fi if [[ -z $DATAPATH ]]; then log "can't find matching repo for $f - make sure it is listed in ${REPOFILE}" continue fi if [[ $CMD == "go" ]]; then NEEDMOUNT=1 elif [[ $CMD == "diff" ]]; then NEEDMOUNT=1 else NEEDMOUNT=0 fi if [[ $NEEDMOUNT -eq 1 ]]; then if [[ $USEUSMB -eq 1 ]]; then mount | grep -q ${DATAPATH} if [[ $? -ne 0 ]]; then # try mounting it. ${USMB} ${USMBNAME} >/dev/null if [[ $? -eq 0 ]]; then log "Mount usmb volume '$USMBNAME': success" else log "Mount usmb volume '$USMBNAME': FAILED" continue fi fi elif [[ $USENFS -eq 1 ]]; then mount | grep -q ${DATAPATH} if [[ $? -ne 0 ]]; then # try mounting it. mkdir -p $DATAPATH mount_nfs -R 1 ${NFSPATH} ${DATAPATH} >/dev/null if [[ $? -eq 0 ]]; then log "Mount nfs volume '$NFSPATH' to $DATAPATH: success" else log "Mount nfs volume '$NFSPATH' to $DATAPATH: FAILED" continue fi fi elif [[ $USELOCALMOUNT -eq 1 ]]; then mount | grep -q ${DATAPATH} if [[ $? -ne 0 ]]; then # try mounting it. mkdir -p $DATAPATH mount ${DATAPATH} >/dev/null if [[ $? -eq 0 ]]; then log "Mount $DATAPATH: success" else log "Mount $DATAPATH: FAILED" continue fi fi fi if ! [[ -e ${DATAPATH} ]]; then log "Error: ${DATAPATH} doesn't exist" continue fi count=`ls ${DATAPATH} | wc -l` if [ $count -le 2 ]; then log "Error: ${DATAPATH} exists but appears to be empty" continue fi fi if [[ -z $GOODREPOS ]]; then GOODREPOS="$f" else GOODREPOS="$GOODREPOS $f" fi done REPOSTOBACKUP="$GOODREPOS" if [[ -z $REPOSTOBACKUP ]]; then log "Error: errors found with all repos. Aborting." exit 1 fi if [[ $TESTMODE -eq 1 ]]; then echo "Would have run '$CMD' on these repos:" for f in $REPOSTOBACKUP; do DATAPATH=$(getdatapath $f) echo " $f -> $DATAPATH" if [[ $NEEDMOUNT -eq 1 ]]; then do_umount fi done exit 0 fi errcount=0 # used for 'check' mode warncount=0 # used for 'check' mode errtext="" for f in $REPOSTOBACKUP; do REPO=${f} DATAPATH=$(getdatapath $REPO) checktag "$f" usmb if [[ $? -eq 0 ]]; then if [[ -z $USMB_PREFIX ]]; then USMBNAME=$f else USMBNAME=`echo "${DATAPATH}" | sed -e "s,${USMB_PREFIX}/\(.*\).*,\1,"` fi USEUSMB=1 else USMBNAME="" USEUSMB=0 fi checktag "$f" nfs if [[ $? -eq 0 ]]; then NFSNAME=`echo "${DATAPATH}" | sed -e "s,${NFS_PREFIX}/\(.*\).*,\1,"` NFSPATH="${DEF_NFS_SERVER}:${DEF_NFS_SERVER_BASE}/${NFSNAME}" USENFS=1 else NFSNAME="" USENFS=0 fi checktag "$f" localmount if [[ $? -eq 0 ]]; then USELOCALMOUNT=1 else USELOCALMOUNT=0 fi export REPO_PATH=`getrepopath "$f"` if [[ $? -eq 0 ]]; then USINGDEFAULT=0 else USINGDEFAULT=1 fi if [[ $CMD == "go" ]]; then NEEDMOUNT=1 elif [[ $CMD == "diff" ]]; then NEEDMOUNT=1 else NEEDMOUNT=0 fi mode=`getmode "$f"` SPEEDOPTS="" AUTHOPTS="" OTHEROPTS="" CONNECTIONOPTS="" if [[ $mode == "restic" ]]; then 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 SPEEDOPTS="" else SPEEDOPTS="--limit-upload $KSPEED" fi if [[ -z $CONNECTIONS ]]; then CONNECTIONSOPTS="" else CONNECTIONSOPTS="-o b2.connections=${CONNECTIONS}" fi if [[ $VERBOSE -eq 1 ]]; then OTHEROPTS="$OTHEROPTS -v" fi export RESTIC_EXCLUDEFILE=`getrepoexcludefile "$f"` if [[ ! -z $RESTIC_PASSWORD_FILE ]]; then OTHEROPTS="$OTHEROPTS --exclude-file=${RESTIC_EXCLUDEFILE}" fi OTHEROPTS="$OTHEROPTS $RESTICOPTS" elif [[ $mode == "rsync" ]]; then # rsync MYREPO="rsync: $REPO_PATH" 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 xx in $list; do eval val='$'$xx if [[ -z $val ]]; then echo "Error - \$$xx not set. Please update ${RCFILE}." echo "" usage-rc exit 1 fi done if [[ -z $KSPEED ]]; then SPEEDOPTS="" else SPEEDOPTS="--bwlimit=${KSPEED}k" fi CONNECTIONSOPTS="" else # rclone MYREPO="rclone: $REPO_PATH" export RCLONE_REPOSITORY="$REPO_PATH" if [[ -z $KSPEED ]]; then SPEEDOPTS="" else SPEEDOPTS="--bwlimit=${KSPEED}k" fi if [[ -z $CONNECTIONS ]]; then CONNECTIONSOPTS="" else CONNECTIONSOPTS="--transfers=${CONNECTIONS}" fi fi if [[ ! $CMD == "check" ]]; then text="Starting '$CMD' on repo '$REPO' [$DATAPATH <-> $MYREPO]" log "$text" 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 (age $age 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 [[ $CRONMODE -eq 1 ]]; then ${RESTIC} backup $AUTHOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $DATAPATH 2>&1 | egrep "^(Added|processed|snapshot)" >> ${LOG} else ${RESTIC} backup $AUTHOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $DATAPATH 2>&1 >> ${LOG} fi rv=$? elif [[ $CMD == "ls" ]]; then ${RESTIC} snapshots $AUTHOPTS $CONNECTIONSOPTS 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "stats" ]]; then ${RESTIC} stats $AUTHOPTS $CONNECTIONSOPTS 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "diff" ]]; then log "Error: diff not supported in restic." rv=1 elif [[ $CMD == "init" ]]; then # check whether it already exists first! ${RESTIC} stats $AUTHOPTS $CONNECTIONSOPTS >/dev/null 2>&1 if [ $? -eq 0 ]; then log "ERROR: Repo ${REPO} already exists. Aborting." rv=1 else cmdtorun="${RESTIC} init $AUTHOPTS $CONNECTIONSOPTS" if [[ $VERBOSE -eq 1 ]]; then log "export RESTIC_REPOSITORY=\"$REPO_PATH\"" log "export RESTIC_PASSWORD_FILE=`getrepopassfile \"$f\"`" log "will run: [${cmdtorun}]" fi errtext=`${RESTIC} init $AUTHOPTS $CONNECTIONSOPTS 2>&1` rv=$? fi elif [[ $CMD == "forget" ]]; then # age out stuff after RESTIC_KEEPDAYS days 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} rv=$? ${RESTIC} prune $AUTHOPTS 2>&1 | egrep "^(repository contain|found|will|remove)" >> ${LOG} else log "Error: invalid command $CMD" rv=1 fi elif [[ $mode == "rsync" ]]; then REMOTE="" if [[ $CMD == "go" ]]; then #echo run ${RSYNC} ${RSYNC_OPTIONS} $DATAPATH/ ${RSYNC_REPOSITORY} 2>&1 >> ${LOG} #exit 1 ${RSYNC} ${RSYNC_OPTIONS} $DATAPATH/ ${RSYNC_REPOSITORY} 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "ls" ]]; then ssh ${DEF_RSYNC_USER}@${DEF_RSYNC_SERVER} ls ${RSYNC_FULLDIR} 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "stats" ]]; then echo "Size of remote data for ${REPO}:" ssh ${DEF_RSYNC_USER}@${DEF_RSYNC_SERVER} du -hs ${RSYNC_FULLDIR} 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "diff" ]]; then ${RSYNC} ${RSYNC_OPTIONS} -n $DATAPATH/ ${RSYNC_REPOSITORY} 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "init" ]]; then # check whether it already exists first! ssh ${DEF_RSYNC_USER}@${DEF_RSYNC_SERVER} ls -d ${RSYNC_FULLDIR} 2>&1 >> ${LOG} if [ $? -eq 0 ]; then log "ERROR: Repo ${REPO} already exists. Aborting." else ssh ${DEF_RSYNC_USER}@${DEF_RSYNC_SERVER} mkdir -p ${RSYNC_FULLDIR} 2>&1 >>${LOG} if [ $? -eq 0 ]; then log "Created directory ${RSYNC_FULLDIR}..." else log "Creation of ${RSYNC_FULLDIR} failed." fi fi elif [[ $CMD == "forget" ]]; then log "Error: forget not supported for rsync mode." rv=1 else log "Error: invalid command $CMD" rv=1 fi else # rclone REMOTE="" if [[ $CMD == "go" ]]; then ${RCLONE} sync $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $DATAPATH $RCLONE_REPOSITORY 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "ls" ]]; then ${RCLONE} ls $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $RCLONE_REPOSITORY 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "stats" ]]; then ${RCLONE} size $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $RCLONE_REPOSITORY 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "diff" ]]; then ${RCLONE} check $RCLONEOPTS $CONNECTIONSOPTS $SPEEDOPTS $OTHEROPTS $RCLONE_REPOSITORY 2>&1 >> ${LOG} rv=$? elif [[ $CMD == "init" ]]; then # check whether it already exists first! ${RCLONE} size $RCLONEOPTS $RCLONE_REPOSITORY >/dev/null 2>&1 if [ $? -eq 0 ]; then log "ERROR: Repo ${REPO} already exists. Aborting." else # does 'remote' exist? ${RCLONE} listremotes | grep -q remote: >/dev/null 2>&1 rv=$? if [ $rv -ne 0 ]; then log "Rclone remote doesn't exist - creating it..." ${RCLONE} $RCLONEOPTS config create remote b2 account $B2_APP_ID key $B2_APP_KEY >>${LOG} rv=$? if [ $rv -ne 0 ]; then log "Rclone remote init failed." exit 1 fi fi if [ $rv -eq 0 ]; then log "Creating B2 bucket for $RCLONE_REPOSITORY..." # create the bucket ${RCLONE} $RCLONEOPTS mkdir $RCLONE_REPOSITORY >>${LOG} else log "Rclone bucket creation of $RCLONE_REPOSITORY failed." fi fi elif [[ $CMD == "forget" ]]; then log "Error: forget not supported for rclone mode." rv=1 else log "Error: invalid command $CMD" rv=1 fi fi if [[ ! $CMD == "check" ]]; then # Record result updatestats $f $CMD $rv fi if [[ $rv -eq 0 ]]; then if [[ $NEEDMOUNT -eq 1 ]]; then do_umount fi elif [[ ! $CMD == "check" ]]; then log "Error: '$CMD' on repo '$REPO' failed" if [[ ! -z $errtext ]]; then log "$errtext" fi fi if [[ ! $CMD == "check" ]]; then log "Finished '$CMD' on repo '$REPO'" fi 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