diff --git a/backup.sh b/backup.sh index 4f5bc6a..3d7421f 100755 --- a/backup.sh +++ b/backup.sh @@ -1,4 +1,5 @@ #!/usr/local/bin/bash + # # Hjemmesnekret script som tar backup av PVV-servere. # @@ -7,7 +8,7 @@ # Oppdatert av pederbs og yorinad 2017.02.04 # -#for å legge til en backup jobb: +# for å legge til en backup jobb: # zfs create principal/backupz/%name% # #sørg for at principal kan logge inn som brukerene på boksen uten passord: @@ -16,234 +17,296 @@ # -echo 'PVV; hjemmelaget backupscript ($Id: backup.sh,v 1.16 2025/05/24 17:22:00 root Exp root $)' +echo "PVV; hjemmelaget backupscript (\$ git commit sha: $(cd /backupz && git rev-parse HEAD) \$)" echo -echo $(date) +date # Blir brukt som navn på ZFS-snapshot og logger. -snapshot=`date +%Y%m%d` -if [ "x$1" = "xfull" ]; then # Fullbackupen starter før midnat, legg på en dag - snapshot=`date -v +1d +%Y%m%d` +snapshot="$(date +%Y%m%d)" +if [ "$1" = "full" ]; then # Fullbackupen starter før midnatt, legg på en dag + snapshot=$(date -v +1d +%Y%m%d) fi -lockfile="/backupz/backup.sh.lock" +lockfile="/backupz/backup.sh.lock" if [ -e $lockfile ]; then - pid=$(cat $lockfile) + pid="$(cat $lockfile)" # TODO: Bruk bedre metode for å finne prosess. - if ps -p $pid ; then - echo "Backup kjører allerede:" `cat $lockfile` - exit -1 + if ps -p "$pid"; then + echo "Backup kjører allerede: $pid" + exit 1 fi echo "Forrige backup ble avbrutt, rydder opp..." - rm $lockfile + rm "$lockfile" - zfs snapshot -r principal/backupz@avbrutt_${snapshot} && \ + zfs snapshot -r "principal/backupz@avbrutt_${snapshot}" && \ echo "ZFS-snapshot OK." || echo "ZFS-snapshot FEILET!" - # TODO: zfs rollback til forrige komplette backup. + # TODO: zfs rollback til forrige komplette backup. echo "Ferdig med oppryddingen." fi # Fang SIGINT, vi vil rydde opp om vi blir avbrutt. -trap "rm $lockfile; echo 'Avbrutt, sletter låsfil...'; exit -2" SIGINT -echo $$ > $lockfile +on_sigint() { + rm $lockfile + echo 'Avbrutt, sletter låsfil...' + exit 2 +} +trap on_sigint SIGINT + +echo "$$" > "$lockfile" echo "Sjekker at det er nok ledig plass på disken..." zfs get available principal/backupz + #while [ $(/bin/df /backupz/ | /usr/bin/awk '/^backupz/{print $4}' ) -lt 100000000 ] ; do -while [ $( zfs get -Hp available principal/backupz | cut -f3 ) -lt 50000000000 ] ; do - echo; echo "Disken er nesten full, rydder"; echo +while [ "$(zfs get -Hp available principal/backupz | cut -f3)" -lt 50000000000 ] ; do + echo; + echo "Disken er nesten full, rydder"; + echo + min_backups=5 - if [ $(zfs list -t snapshot | grep backupz@ | wc -l) -lt $min_backups ]; then - echo; echo "Mindre enn $min_backups backups lagret, feiger ut fra sletting"; echo + if [ "$(zfs list -t snapshot | grep -c "backupz@")" -lt "$min_backups" ]; then + echo; + echo "Mindre enn $min_backups backups lagret, feiger ut fra sletting"; + echo break; fi + oldest=$(zfs list -t snapshot | grep backupz@ | head -n1 | tr @ ' ' | awk '{print $2}') echo "Kjører zfs destroy på alle disker @$oldest" for d in $(zfs list | grep ^principal/backupz | awk '{print $1}'); do zfs destroy "$d@$oldest" done + zfs get available principal/backupz echo done - - echo "Starter backup..." - -#export RSYNC_RSH="ssh -c arcfour -v" -export RSYNC_RSH="ssh -v" -rsync="/usr/local/bin/rsync" -rsync_flags="--archive --hard-links --one-file-system --compress --delete --numeric-ids --stats --inplace --relative --exclude=/.zfs/" -logdir="/backupz/log" - -# Gjør selve overføringen. -# Start på en liste over PID vi skal vente på. -venteproc="" - -# Ikke kjoer med --checkum. Den er nyttig senere for aa detektere bitraate. -# # Gjør "full"-backup på søndager. -# if [ "x$1" = "xfull" ]; then # Det er søndag -# echo "Det er søndag; tar «full»-backup." -# rsync_flags="${rsync_flags} --checksum" -# fi - echo "Snapshot ID: $snapshot" echo echo +### Liste over vertsmaskiner og hva som skal tas backup av. ### -# ameno -command="${rsync} ${rsync_flags} \ - --log-file=${logdir}/ameno.log.$snapshot \ - --exclude=/var/cache/ \ - --exclude=/var/lib/snapd/ \ - --exclude=/var/log/journal/ \ - ameno:/ \ - ameno:/boot/firmware \ - /backupz/ameno/current/" -$command >${logdir}/ameno.out.$snapshot 2>&1 & -venteproc="$venteproc $!" -echo "Startet $!: $command" +# TODO: kanskje noe av dette enklere kunne blitt uttrykt +# med en egen json-fil og litt jq-magi? -# # knakelibrak (wiki) -# command="${rsync} ${rsync_flags}\ -# wiki:/var/lib/mediawiki /backupz/wiki/" -# $command >${logdir}/wiki.out.$snapshot 2>&1 & -# venteproc="$venteproc $!" -# echo "Startet $!: $command" +# Liste over vertsmaskiner som skal tas backup av. +declare hosts=() -# # knakelibrak (databases) -# command="${rsync} ${rsync_flags}\ -# knakelibrak:/var/backups/databases /backupz/databases/" -# $command >${logdir}/knakelibrak.out.$snapshot 2>&1 & -# venteproc="$venteproc $!" -# echo "Startet $!: $command" +# SSH-vertsnavn hvis det er forskjellig fra vertsnavnet i listen. +declare -A host_ssh_hostname=() -# # jokum (synapse) -# command="${rsync} ${rsync_flags}\ -# jokum:/data/synapse/ /backupz/jokum/synapse/" -# $command >${logdir}/jokum.out.$snapshot 2>&1 & -# venteproc="$venteproc $!" -# echo "Startet $!: $command" +# Backup-katalog hvis den er forskjellig fra vertsnavnet i listen. +declare -A hosts_output_dir=() -# # skrotnisse -# command="${rsync} ${rsync_flags}\ -# skrotnisse:/var/www/ skrotnisse:/srv/ /backupz/skrotnisse/" -# $command >${logdir}/skrotnisse.out.$snapshot 2>&1 & -# venteproc="$venteproc $!" -# echo "Startet $!: $command" +hosts+=("ameno") +declare -r ameno_includes=( + "/" + "/boot/firmware" +) +declare -r ameno_excludes=( + "/var/cache/" + "/var/lib/snapd/" + "/var/log/journal/" +) -# # dash8 -# command="${rsync} ${rsync_flags}\ -# dash8:/var/lib/bitlbee/ /backupz/dash8/" -# $command >${logdir}/dash8.out.$snapshot 2>&1 & -# venteproc="$venteproc $!" -# echo "Startet $!: $command" +# knakelibrak (wiki) +# hosts+=("knakelibrak_wiki") +# host_ssh_hostname["knakelibrak_wiki"]="wiki" +# hosts_output_dir["knakelibrak_wiki"]="wiki" +# declare -r wiki_includes=( +# "/var/lib/mediawiki" +# ) +# declare -r wiki_excludes=() -# tim døde, tom tok over men har ikke squirrelmail (4.feb 2019) -# tim (web) -#command="${rsync} ${rsync_flags}\ -# tim:/var/lib/squirrelmail /backupz/web/" -#$command >${logdir}/tim.out.$snapshot 2>&1 & -#venteproc="$venteproc $!" -#echo "Startet $!: $command" +# knakelibrak (databases) +# hosts+=("knakelibrak_databases") +# host_ssh_hostname["knakelibrak_databases"]="knakelibrak" +# hosts_output_dir["knakelibrak_databases"]="databases" +# declare -r knakelibrak_databases_includes=( +# "/var/backups/databases" +# ) +# declare -r knakelibrak_databases_excludes=() -# homepvv -# Maa ha --one-file-system, ellers henger rsync pga. gvfs. -command="${rsync} ${rsync_flags} \ - --log-file=${logdir}/homepvv.log.$snapshot \ - --exclude-from=/backupz/homepvv.exclude \ - homepvv:/ \ - homepvv:/boot \ - homepvv:/export/home/pvv \ - homepvv:/var \ - /backupz/homepvv/" -$command >${logdir}/homepvv.out.$snapshot 2>&1 & -venteproc="$venteproc $!" -echo "Startet $!: $command" +# jokum (synapse) +# hosts+=("jokum_synapse") +# host_ssh_hostname["jokum_synapse"]="jokum" +# hosts_output_dir["jokum_synapse"]="jokum/synapse" +# declare -r jokum_synapse_includes=( +# "/data/synapse/" +# ) +# declare -r jokum_synapse_excludes=() + +# skrotnisse +# hosts+=("skrotnisse") +# declare -r skrotnisse_includes=( +# "/var/www/" +# "/srv/" +# ) +# declare -r skrotnisse_excludes=() + +# dash8 +# hosts+=("dash8") +# declare -r dash8_includes=( +# "/var/lib/bitlbee/" +# ) +# declare -r dash8_excludes=() + +# tim +# hosts+=("tim") +# hosts_output_dir["tim"]="web" +# declare -r tim_includes=( +# "/var/lib/squirrelmail" +# ) +# declare -r tim_excludes=() + +hosts+=("homepvv") +declare -r homepvv_includes=( + "/" + "/boot" + "/export/home/pvv" + "/var" +) +declare -r homepvv_excludes=( + # Se ./homepvv.exclude - den skal bli plukket opp automatisk +) # innovation # Minecraft-verden kopieres fra /var/backups/minecraft/current/ istf. # /srv/minecraft-pvv/. -command="${rsync} ${rsync_flags} \ - --log-file=${logdir}/innovation.log.$snapshot \ - --exclude=/srv/minecraft-pvv/ \ - --exclude=/var/cache/ \ - --exclude=/var/db/freebsd-update/files/ \ - innovation:/ \ - innovation:/boot/efi \ - /backupz/innovation/current/" -$command >${logdir}/innovation.out.$snapshot 2>&1 & -venteproc="$venteproc $!" -echo "Startet $!: $command" +hosts+=("innovation") +declare -r innovation_includes=( + "/" + "/boot/efi" +) +declare -r innovation_excludes=( + "/srv/minecraft-pvv/" + "/var/cache/" + "/var/db/freebsd-update/files/" +) -# # lommel -# command="${rsync} ${rsync_flags} --exclude-from=/backupz/lommel.exclude \ -# lommel:/ /backupz/lommel/" -# $command >${logdir}/lommel.out.$snapshot 2>&1 & -# venteproc="$venteproc $!" -# echo "Startet $!: $command" +# hosts+=("lommel") +# declare -r lommel_includes=( +# "/" +# ) +# declare -r lommel_excludes=( + # se ./lommel.exclude - den skal bli plukket opp automatisk +# ) -# sleipner -command="${rsync} ${rsync_flags} \ - --log-file=${logdir}/sleipner.log.$snapshot \ - --exclude=/scratch/ \ - --exclude=/var/cache/ \ - sleipner:/ \ - /backupz/sleipner/current/" -$command >${logdir}/sleipner.out.$snapshot 2>&1 & -venteproc="$venteproc $!" -echo "Startet $!: $command" +hosts+=("sleipner") +declare -r sleipner_includes=( + "/" +) +declare -r sleipner_excludes=( + "/scratch/" + "/var/cache/" +) -# # Spikkjeposche -# command="${rsync} ${rsync_flags} \ -# spikkjeposche:/usr/local/www \ -# spikkjeposche:/usr/local/etc/lighttpd \ -# spikkjeposche:/etc/ssl/private \ -# /backupz/spikkjeposche/" -# $command >${logdir}/spikkjeposche.out.$snapshot 2>&1 & -# venteproc="$venteproc $!" -# echo "Startet $!: $command" +# hosts+=("spikkjeposche") +# declare -r spikkjeposche_includes=( +# "/usr/local/www" +# "/usr/local/etc/lighttpd" +# "/etc/ssl/private" +# ) +# declare -r spikkjeposche_excludes=() -# tom -command="${rsync} ${rsync_flags} \ - --log-file=${logdir}/tom.log.$snapshot \ - --exclude=/var/cache/ \ - tom:/ \ - tom:/boot/efi \ - /backupz/tom/current/" -$command >${logdir}/tom.out.$snapshot 2>&1 & -venteproc="$venteproc $!" -echo "Startet $!: $command" +hosts+=("tom") +declare -r tom_includes=( + "/" + "/boot/efi" +) +declare -r tom_excludes=( + "/var/cache/" +) +### Slutt på liste over vertsmaskiner og hva som skal tas backup av. ### +#export RSYNC_RSH="ssh -c arcfour -v" +export RSYNC_RSH="ssh -v" +declare -r rsync="/usr/local/bin/rsync" +rsync_flags=( + --archive + --hard-links + --one-file-system + --compress + --delete + --numeric-ids + --stats + --inplace + --relative + --exclude=/.zfs/ +) +declare -r logdir="/backupz/log" +# Gjør selve overføringen. +# Start på en liste over PID vi skal vente på. +declare -a venteproc=() +# Ikke kjoer med --checkum. Den er nyttig senere for aa detektere bitraate. +# # Gjør "full"-backup på søndager. +# if [ "$1" = "full" ]; then # Det er søndag +# echo "Det er søndag; tar «full»-backup." +# rsync_flags="${rsync_flags[@]} --checksum" +# fi -## Andre ting som skal kopieres her... +for host in "${hosts[@]}"; do + command=( + "$rsync" + "${rsync_flags[@]}" + "--log-file=${logdir}/${host}.log.$snapshot" + ) + exclude_paths_var="${host}_excludes[@]" + exclude_paths=("${!exclude_paths_var}") + for exclude in "${exclude_paths[@]}"; do + command+=("--exclude=${exclude}") + done + + if [ -f "/backupz/${host}.exclude" ]; then + command+=("--exclude-from=/backupz/${host}.exclude") + fi + + include_paths_var="${host}_includes[@]" + include_paths=("${!include_paths_var}") + if [ "${#include_paths[@]}" -eq 0 ]; then + echo "Ingen inkluderingsstier for vert $host, hopper over." + continue + fi + + for include in "${include_paths[@]}"; do + command+=("${host_ssh_hostname[$host]:-$host}:$include") + done + + command+=("/backupz/${hosts_output_dir[$host]:-$host}/") + + echo "Starter backup for vert: $host" + "${command[@]}" >"${logdir}/${host}.out.$snapshot" 2>&1 & + venteproc+=("$!") + echo "Startet $!: ${command[*]}" +done echo echo "Rsync er i gang." # Vent til rsync er ferdig. -echo "Venter til rsync er ferdig: $venteproc" -for i in $venteproc ; do - wait $i +echo "Venter til rsync er ferdig: ${venteproc[*]}" +for pid in "${venteproc[@]}" ; do + wait "$pid" feilkode=$? if [ $feilkode -eq 0 ]; then - echo "$i: OK" + echo "$pid: OK" else - echo "$i: Rsync returnerte feil (${feilkode})." + echo "$pid: Rsync returnerte feil (${feilkode})." fi done -echo +echo echo "Rsync er ferdig." # Behoeves ikke da principal ikke har almen brukerinnlogging. @@ -256,14 +319,14 @@ touch /backupz/homepvv/export/home # Ta et zfs snapshot echo "Tar ZFS-snapshot..." -zfs snapshot -r principal/backupz@${snapshot} && \ +zfs snapshot -r "principal/backupz@${snapshot}" && \ echo "ZFS-snapshot ferdig." || echo "ZFS-snapshot FEILET!" echo -echo Ledig plass: $(zfs list -H -o avail principal/backupz) +echo Ledig plass: "$(zfs list -H -o avail principal/backupz)" echo # TODO: Slett enkelte gamle snapshots? echo "Backup ferdig: $(date)" -rm $lockfile +rm "$lockfile" zpool status -xv principal