diff options
author | Erich Eckner <git@eckner.net> | 2016-04-01 09:40:29 +0200 |
---|---|---|
committer | Erich Eckner <git@eckner.net> | 2016-04-01 09:40:29 +0200 |
commit | 61998f2eaabadd4fa531d97e9a42373ff9bc6fbc (patch) | |
tree | 9e7afcb83f4cc30b3aae146a3b7de02415916183 | |
download | hardlinkedBackups-61998f2eaabadd4fa531d97e9a42373ff9bc6fbc.tar.xz |
Initial Commit
-rwxr-xr-x | backup | 115 | ||||
-rw-r--r-- | backup.conf | 24 | ||||
-rwxr-xr-x | lastBackups | 67 |
3 files changed, 206 insertions, 0 deletions
@@ -0,0 +1,115 @@ +#!/bin/bash + +. /etc/backup.conf + +usage() +{ + echo 'usage:' + echo ' backup /tmp/pidFile /path/to/destination/ user@source:path' + echo ' backup /tmp/pidFile /path/to/destination/ user@source:path proxy_user@ssh_host' + echo 'or as a symlink (e.g. in /etc/cron/daily) named after a key of $backups in /etc/backup.conf without arguments' + exit 1 +} + +if [ $# -eq 0 ] +then + backupID="$(basename $0)" + [ -z "${backups[${backupID}]}" ] && usage + set /tmp/${backupID}.pid ${backups[${backupID}]} +fi + +Basis="$2" +pidFile="$1" +QuellIP=$(echo "$3" | sed "s|^[a-zA-Z]*://||; s|^[a-zA-Z]*@||; s|:\?/.*$||") + +if [ "$#" -eq 3 ] +then + Quelle="$3" +elif [ "$#" -eq 4 ] +then + sshHopp="$4" + lokPort=$[$RANDOM/2+8000] + rsyncShell="-e ssh -p${lokPort} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" + tunnelBefehl="ssh -t -t -L${lokPort}:${QuellIP}:22 ${sshHopp}" + HoppIP="${sshHopp#*@}" + Quelle="$(echo "$3" | sed "s|${QuellIP}|127.0.0.1|")" +else + usage +fi + +ping -c1 ${QuellIP} > /dev/null || exit 11 +if [ -n "${HoppIP}" ] +then + ping -c1 ${HoppIP} > /dev/null || exit 11 +fi + +if [ ! -d ${Basis} ] +then + [ $(mount | grep -c "\S\+\s\+\S\+\s\+/var/ftp\s") -eq 0 ] && exit 11 + exit 2 +fi + +neues_Datum=${Basis}/$(date "+%Y_%m_%d") +neues=${Basis}/aktuell +linkdests="" +for s in $(ls -1tr ${Basis} | grep -v aktuell | tail -n20 ) +do + linkdests="${linkdests} --link-dest ${Basis}/${s}" +done + +if [ ! "$(whoami)" == "root" ] +then + echo "I need to be root." + exit 3 +fi + +[ -w ${Basis} ] || exit 11 +[ -e ${neues_Datum} ] && exit 4 +[ -e ${pidFile} ] && exit 5 + +echo $$ > ${pidFile} + +if [ -n "${tunnelBefehl}" ] +then + ${tunnelBefehl} & + backgroundPid=$! + sleep 4 +fi + +for toExclude in ${excludes} +do + excludeArgs="${excludeArgs} --exclude ${toExclude}" +done + +if [ ! -e ${neues} ] +then + mkdir ${neues} +fi +chmod 750 ${neues} +chown erich:root ${neues} +if [ -z "${rsyncShell}" ] +then + rsync -av -x --no-p --no-o --no-g ${linkdests} \ + ${excludeArgs} \ + ${Quelle} ${neues}/ + sleep 1 + rsync ${Quelle} +else + rsync "${rsyncShell}" -av -x --no-p --no-o --no-g ${linkdests} \ + ${excludeArgs} \ + ${Quelle} ${neues}/ + sleep 1 + rsync "${rsyncShell}" ${Quelle} +fi +erg=$? + +[ -n "${backgroundPid}" ] && kill ${backgroundPid} + +if [ ${erg} -eq 0 ] || [ ${erg} -eq 24 ] +then + mv ${neues} ${neues_Datum} + rm ${pidFile} +else + rm ${pidFile} + exit 11 +fi diff --git a/backup.conf b/backup.conf new file mode 100644 index 0000000..0b65488 --- /dev/null +++ b/backup.conf @@ -0,0 +1,24 @@ +#!/bin/bash + +# config file for hardlinkedBackups + +# files/paths to exclude from backup (via --exclude) +excludes=( + "path/to/exclude/from/backup" + "yet/another/one" +) + +# definition of backups to do +declare -A backups + +backups["directBackup"]="/path/to/destination/ user@source:path" +backups["proxiedBackup"]="/path/to/destination/ user@source:path proxy_user@ssh_host" + +# how long to wait for destination directories to appear in lastBackups [seconds] +maxWait=100 + +# how old may backups be before we warn about outdated ones [seconds] +outdatedLimit=$[2*24*60*60] + +# subdirectories which should be appended to the parent directory in the report +recognSubdirRegex="home\|boot\|root\|erich" diff --git a/lastBackups b/lastBackups new file mode 100755 index 0000000..7a03c11 --- /dev/null +++ b/lastBackups @@ -0,0 +1,67 @@ +#!/bin/bash + +. /etc/backup.conf + +unset namen +unset veraltet +unset daten + +for backupID in ${!backups[@]} +do + dest="${backups["${backupID}"]%% *}" + dest="${dest%/}" + while [ ! -d "${dest}" ] && [ ${maxWait} -gt 0 ] + do + sleep 1 + maxWait=$[${maxWait}-1] + done + + lbu=$( + ls -1 ${dest} | \ + grep -v "^aktuell$" | \ + sed "s/^duplicity-\(inc\|full\)\.\(.*\.\)\?\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)T[0-9]\{6\}Z\..*$/\3_\4_\5/" | \ + sort -n | \ + uniq | \ + grep "^[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}$" | \ + tail -n1 + ) + [ "${lbu}" == "" ] && lbu="2000_01_01" + delta=$[$(date +%s) - $(date -d $(echo ${lbu} | sed "s/_//g") +%s)] + namen[${#namen[@]}]="$(basename $(echo ${dest} | sed "s#/\(${recognSubdirRegex}\)\$#_\1#" | sed "s#/rsync\$##; s#/duplicity\$##"))" + [ ${delta} -gt ${outdatedLimit} ] && veraltet[${#veraltet[@]}]="VERALTET!" || veraltet[${#veraltet[@]}]="" + daten[${#daten[@]}]="${lbu}" +done + +nl=0 +vl=0 +dl=0 + +for ((i=0; i<${#namen[@]}; i++)) +{ + [ ${#namen[${i}]} -gt ${nl} ] && nl=${#namen[${i}]} + [ ${#veraltet[${i}]} -gt ${vl} ] && vl=${#veraltet[${i}]} + [ ${#daten[${i}]} -gt ${dl} ] && dl=${#daten[${i}]} +} + +for ((i=0; i<${#namen[@]}; i++)) +{ + while [ ${#namen[${i}]} -lt ${nl} ] + do + namen[${i}]="${namen[${i}]} " + done + while [ ${#veraltet[${i}]} -lt ${vl} ] + do + veraltet[${i}]="${veraltet[${i}]} " + done + while [ ${#daten[${i}]} -lt ${dl} ] + do + daten[${i}]="${daten[${i}]} " + done +} + +for ((i=0; i<${#namen[@]}; i++)) +{ + echo "${daten[${i}]} ${veraltet[${i}]} ${namen[${i}]} ${daten[${i}]}" +} | \ + sort | \ + sed "s/^\S\+\s//" |