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:
parent
cde65f6ff1
commit
f7af0de9f5
351
bare.sh
351
bare.sh
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
if [[ ! $CMD == "check" ]]; then
|
||||||
text="Starting '$CMD' on repo '$REPO' [$DATAPATH <-> $MYREPO]"
|
text="Starting '$CMD' on repo '$REPO' [$DATAPATH <-> $MYREPO]"
|
||||||
log "$text"
|
log "$text"
|
||||||
|
fi
|
||||||
if [[ $mode == "restic" ]]; then
|
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
|
||||||
|
|
||||||
|
if [[ ! $CMD == "check" ]]; then
|
||||||
log "Finished '$CMD' on repo '$REPO'"
|
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
|
||||||
|
|
Loading…
Reference in New Issue