From 12ee00b15013df221ebcf2d9ec2b4788f0d81150 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 02:06:36 +0900 Subject: [PATCH 01/19] backup.sh: diverse opprydding --- backup.sh | 379 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 221 insertions(+), 158 deletions(-) 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 -- 2.52.0 From 5fec1312ffbfe5e2b7ee81324c5ee06a09f000ef Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 02:37:40 +0900 Subject: [PATCH 02/19] =?UTF-8?q?backup.sh:=20rapporter=20ferdige=20rsync-?= =?UTF-8?q?kommandoer=20i=20rekkef=C3=B8lgen=20de=20fullf=C3=B8rer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backup.sh b/backup.sh index 3d7421f..238c8d4 100755 --- a/backup.sh +++ b/backup.sh @@ -296,14 +296,14 @@ echo "Rsync er i gang." # Vent til rsync er ferdig. echo "Venter til rsync er ferdig: ${venteproc[*]}" -for pid in "${venteproc[@]}" ; do - wait "$pid" - feilkode=$? - if [ $feilkode -eq 0 ]; then - echo "$pid: OK" - else - echo "$pid: Rsync returnerte feil (${feilkode})." - fi +while true; do + wait -n -p pid; code=$? + [[ -z "${pid}" ]] && break + if [ $code -eq 0 ]; then + echo "${pid}: OK" + else + echo "${pid}: Rsync returnerte feil (${code})" + fi done echo -- 2.52.0 From 6f725f939da64b70d9b4d47a125e1dcb360e3b22 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 02:45:22 +0900 Subject: [PATCH 03/19] =?UTF-8?q?backup.sh:=20print=20tilh=C3=B8rende=20ve?= =?UTF-8?q?rt=20for=20fullf=C3=B8rte=20rsync=20kommandoer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backup.sh b/backup.sh index 238c8d4..32c6404 100755 --- a/backup.sh +++ b/backup.sh @@ -246,7 +246,7 @@ declare -r logdir="/backupz/log" # Gjør selve overføringen. # Start på en liste over PID vi skal vente på. -declare -a venteproc=() +declare -A venteproc=() # Ikke kjoer med --checkum. Den er nyttig senere for aa detektere bitraate. # # Gjør "full"-backup på søndager. @@ -287,7 +287,7 @@ for host in "${hosts[@]}"; do echo "Starter backup for vert: $host" "${command[@]}" >"${logdir}/${host}.out.$snapshot" 2>&1 & - venteproc+=("$!") + venteproc[$!]="$host" echo "Startet $!: ${command[*]}" done @@ -295,14 +295,14 @@ echo echo "Rsync er i gang." # Vent til rsync er ferdig. -echo "Venter til rsync er ferdig: ${venteproc[*]}" +echo "Venter til rsync er ferdig: ${!venteproc[*]}" while true; do wait -n -p pid; code=$? [[ -z "${pid}" ]] && break if [ $code -eq 0 ]; then - echo "${pid}: OK" + echo "${pid} (${venteproc["$pid"]:-???}): OK" else - echo "${pid}: Rsync returnerte feil (${code})" + echo "${pid} (${venteproc["$pid"]:-???}): Rsync returnerte feil (${code})" fi done -- 2.52.0 From 8ada9f24a6785a96371cbf36394f8ef29754a839 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 02:55:35 +0900 Subject: [PATCH 04/19] =?UTF-8?q?backup.sh:=20sleng=20p=C3=A5=20flere=20`d?= =?UTF-8?q?eclare`=20og=20kommentarer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 84 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/backup.sh b/backup.sh index 32c6404..df742a3 100755 --- a/backup.sh +++ b/backup.sh @@ -23,15 +23,15 @@ date # Blir brukt som navn på ZFS-snapshot og logger. -snapshot="$(date +%Y%m%d)" +declare -r 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) + declare -r snapshot=$(date -v +1d +%Y%m%d) fi -lockfile="/backupz/backup.sh.lock" +declare -r lockfile="/backupz/backup.sh.lock" if [ -e $lockfile ]; then - pid="$(cat $lockfile)" + declare -r pid="$(cat $lockfile)" # TODO: Bruk bedre metode for å finne prosess. if ps -p "$pid"; then @@ -69,7 +69,7 @@ while [ "$(zfs get -Hp available principal/backupz | cut -f3)" -lt 50000000000 ] echo "Disken er nesten full, rydder"; echo - min_backups=5 + declare -ri min_backups=5 if [ "$(zfs list -t snapshot | grep -c "backupz@")" -lt "$min_backups" ]; then echo; echo "Mindre enn $min_backups backups lagret, feiger ut fra sletting"; @@ -77,7 +77,7 @@ while [ "$(zfs get -Hp available principal/backupz | cut -f3)" -lt 50000000000 ] break; fi - oldest=$(zfs list -t snapshot | grep backupz@ | head -n1 | tr @ ' ' | awk '{print $2}') + declare -r 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" @@ -98,7 +98,7 @@ echo # med en egen json-fil og litt jq-magi? # Liste over vertsmaskiner som skal tas backup av. -declare hosts=() +declare -a hosts=() # SSH-vertsnavn hvis det er forskjellig fra vertsnavnet i listen. declare -A host_ssh_hostname=() @@ -106,12 +106,13 @@ declare -A host_ssh_hostname=() # Backup-katalog hvis den er forskjellig fra vertsnavnet i listen. declare -A hosts_output_dir=() +# ameno hosts+=("ameno") -declare -r ameno_includes=( +declare -ra ameno_includes=( "/" "/boot/firmware" ) -declare -r ameno_excludes=( +declare -ra ameno_excludes=( "/var/cache/" "/var/lib/snapd/" "/var/log/journal/" @@ -121,60 +122,61 @@ declare -r ameno_excludes=( # hosts+=("knakelibrak_wiki") # host_ssh_hostname["knakelibrak_wiki"]="wiki" # hosts_output_dir["knakelibrak_wiki"]="wiki" -# declare -r wiki_includes=( +# declare -ra wiki_includes=( # "/var/lib/mediawiki" # ) -# declare -r wiki_excludes=() +# declare -ra wiki_excludes=() # knakelibrak (databases) # hosts+=("knakelibrak_databases") # host_ssh_hostname["knakelibrak_databases"]="knakelibrak" # hosts_output_dir["knakelibrak_databases"]="databases" -# declare -r knakelibrak_databases_includes=( +# declare -ra knakelibrak_databases_includes=( # "/var/backups/databases" # ) -# declare -r knakelibrak_databases_excludes=() +# declare -ra knakelibrak_databases_excludes=() # jokum (synapse) # hosts+=("jokum_synapse") # host_ssh_hostname["jokum_synapse"]="jokum" # hosts_output_dir["jokum_synapse"]="jokum/synapse" -# declare -r jokum_synapse_includes=( +# declare -ra jokum_synapse_includes=( # "/data/synapse/" # ) -# declare -r jokum_synapse_excludes=() +# declare -ra jokum_synapse_excludes=() # skrotnisse # hosts+=("skrotnisse") -# declare -r skrotnisse_includes=( +# declare -ra skrotnisse_includes=( # "/var/www/" # "/srv/" # ) -# declare -r skrotnisse_excludes=() +# declare -ra skrotnisse_excludes=() # dash8 # hosts+=("dash8") -# declare -r dash8_includes=( +# declare -ra dash8_includes=( # "/var/lib/bitlbee/" # ) -# declare -r dash8_excludes=() +# declare -ra dash8_excludes=() # tim # hosts+=("tim") # hosts_output_dir["tim"]="web" -# declare -r tim_includes=( +# declare -ra tim_includes=( # "/var/lib/squirrelmail" # ) -# declare -r tim_excludes=() +# declare -ra tim_excludes=() +# microbel (hjemmeområder) hosts+=("homepvv") -declare -r homepvv_includes=( +declare -ra homepvv_includes=( "/" "/boot" "/export/home/pvv" "/var" ) -declare -r homepvv_excludes=( +declare -ra homepvv_excludes=( # Se ./homepvv.exclude - den skal bli plukket opp automatisk ) @@ -182,47 +184,51 @@ declare -r homepvv_excludes=( # Minecraft-verden kopieres fra /var/backups/minecraft/current/ istf. # /srv/minecraft-pvv/. hosts+=("innovation") -declare -r innovation_includes=( +declare -ra innovation_includes=( "/" "/boot/efi" ) -declare -r innovation_excludes=( +declare -ra innovation_excludes=( "/srv/minecraft-pvv/" "/var/cache/" "/var/db/freebsd-update/files/" ) +# lommel # hosts+=("lommel") -# declare -r lommel_includes=( +# declare -ra lommel_includes=( # "/" # ) -# declare -r lommel_excludes=( +# declare -ra lommel_excludes=( # se ./lommel.exclude - den skal bli plukket opp automatisk # ) +# sleipner hosts+=("sleipner") -declare -r sleipner_includes=( +declare -ra sleipner_includes=( "/" ) -declare -r sleipner_excludes=( +declare -ra sleipner_excludes=( "/scratch/" "/var/cache/" ) +# spikkjeposche # hosts+=("spikkjeposche") -# declare -r spikkjeposche_includes=( +# declare -ra spikkjeposche_includes=( # "/usr/local/www" # "/usr/local/etc/lighttpd" # "/etc/ssl/private" # ) -# declare -r spikkjeposche_excludes=() +# declare -ra spikkjeposche_excludes=() +# tom hosts+=("tom") -declare -r tom_includes=( +declare -ra tom_includes=( "/" "/boot/efi" ) -declare -r tom_excludes=( +declare -ra tom_excludes=( "/var/cache/" ) ### Slutt på liste over vertsmaskiner og hva som skal tas backup av. ### @@ -230,7 +236,7 @@ declare -r tom_excludes=( #export RSYNC_RSH="ssh -c arcfour -v" export RSYNC_RSH="ssh -v" declare -r rsync="/usr/local/bin/rsync" -rsync_flags=( +declare -ra rsync_flags=( --archive --hard-links --one-file-system @@ -256,14 +262,14 @@ declare -A venteproc=() # fi for host in "${hosts[@]}"; do - command=( + declare -a command=( "$rsync" "${rsync_flags[@]}" "--log-file=${logdir}/${host}.log.$snapshot" ) - exclude_paths_var="${host}_excludes[@]" - exclude_paths=("${!exclude_paths_var}") + declare exclude_paths_var="${host}_excludes[@]" + declare -a exclude_paths=("${!exclude_paths_var}") for exclude in "${exclude_paths[@]}"; do command+=("--exclude=${exclude}") done @@ -272,8 +278,8 @@ for host in "${hosts[@]}"; do command+=("--exclude-from=/backupz/${host}.exclude") fi - include_paths_var="${host}_includes[@]" - include_paths=("${!include_paths_var}") + declare include_paths_var="${host}_includes[@]" + declare -a include_paths=("${!include_paths_var}") if [ "${#include_paths[@]}" -eq 0 ]; then echo "Ingen inkluderingsstier for vert $host, hopper over." continue -- 2.52.0 From 037182e2e050b964ffe6bc4b776be631e3e66147 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 03:20:23 +0900 Subject: [PATCH 05/19] =?UTF-8?q?backup.sh:=20sjekk=20at=20verkt=C3=B8y=20?= =?UTF-8?q?er=20p=C3=A5=20plass=20f=C3=B8r=20vi=20kj=C3=B8rer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/backup.sh b/backup.sh index df742a3..10e29ae 100755 --- a/backup.sh +++ b/backup.sh @@ -16,6 +16,35 @@ #ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsCm6f5JOlKDbZMiQ6rXvU35QU4Gs/WKKlZymXtFxPhK5jBoZskQjNhfsr+peuhnZ1y+04L9qEBkN3jN0ThROaRaKSFVWfnMnij7pEB0bmJRxDmkQsHL7YsAm6tPn8116tt9m9ASPYE5RpnaDGtxTP7uXa42URvwXdvWY618tdX4z39JG9f85KYexhwRbhaBMLnSPH6JKCKu1tTBwr7oEbuhLFrFXQwqWRip/oN/6/eSxnIrwaey1GM+CdNfeGh/0OeQJ4XIUas2WbgiQRw6Dkxo32FeFS5LVaOYWRys6W3Znw9a9yOYImjJ8WUmiwSeN2bksUizNBNA1HBhoKGM5b root@alphys # +declare -ra required_tools=( + rsync + ssh + zfs + zpool + awk +) +for tool in "${required_tools[@]}"; do + if ! command -v "$tool" >/dev/null 2>&1; then + echo "Mangler påkrevd verktøy: $tool" + exit 1 + fi +done + +if [ "$(id -u)" -ne 0 ]; then + echo "Må kjøres som root!" + exit 1 +fi + +# 5.1 er minimum pga. wait '-p' flagget. +declare -r minimum_bash_major_version="5" +declare -r minimum_bash_minor_version="1" +if [ \ + "${BASH_VERSINFO[0]}" -lt "$minimum_bash_major_version" ] || \ + { [ "${BASH_VERSINFO[0]}" -eq "$minimum_bash_major_version" ] && \ + [ "${BASH_VERSINFO[1]}" -lt "$minimum_bash_minor_version" ]; }; then + echo "Må kjøres med bash versjon $minimum_bash_major_version eller nyere!" + exit 1 +fi echo "PVV; hjemmelaget backupscript (\$ git commit sha: $(cd /backupz && git rev-parse HEAD) \$)" echo -- 2.52.0 From 5f2133a5f1109db2d173f21a04c5afa96a1d4c85 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 03:25:30 +0900 Subject: [PATCH 06/19] =?UTF-8?q?backup.sh:=20m=C3=A5l=20kj=C3=B8retiden?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backup.sh b/backup.sh index 10e29ae..572b9c6 100755 --- a/backup.sh +++ b/backup.sh @@ -262,6 +262,8 @@ declare -ra tom_excludes=( ) ### Slutt på liste over vertsmaskiner og hva som skal tas backup av. ### +declare -ri start_time="$(date +%s)" + #export RSYNC_RSH="ssh -c arcfour -v" export RSYNC_RSH="ssh -v" declare -r rsync="/usr/local/bin/rsync" @@ -344,6 +346,10 @@ done echo echo "Rsync er ferdig." +declare -ri end_time="$(date +%s)" +declare -ri elapsed_time="$((end_time - start_time))" +printf 'Tid brukt på rsync: %03d:%02d:%02d\n' $((elapsed_time/3600)) $(((elapsed_time/60)%60)) $((elapsed_time%60)) + # Behoeves ikke da principal ikke har almen brukerinnlogging. # # Gjør hjemmemappene lesbare bare for brukeren. # find /backupz/homepvv/export/home/pvv -maxdepth 2 -mindepth 2 -exec chmod 700 {} \; -- 2.52.0 From 7174b1b8745f303c0abe1224f6e3fe63ef513eb4 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 03:38:37 +0900 Subject: [PATCH 07/19] backup.sh: litt mer beskrivende navn for et par variabler --- backup.sh | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/backup.sh b/backup.sh index 572b9c6..7126b2d 100755 --- a/backup.sh +++ b/backup.sh @@ -50,28 +50,27 @@ echo "PVV; hjemmelaget backupscript (\$ git commit sha: $(cd /backupz && git rev echo date - # Blir brukt som navn på ZFS-snapshot og logger. -declare -r snapshot="$(date +%Y%m%d)" +declare -r snapshot_date="$(date +%Y%m%d)" if [ "$1" = "full" ]; then # Fullbackupen starter før midnatt, legg på en dag - declare -r snapshot=$(date -v +1d +%Y%m%d) + declare -r snapshot_date=$(date -v +1d +%Y%m%d) fi declare -r lockfile="/backupz/backup.sh.lock" if [ -e $lockfile ]; then - declare -r pid="$(cat $lockfile)" + declare -r existing_pid="$(cat $lockfile)" # TODO: Bruk bedre metode for å finne prosess. - if ps -p "$pid"; then - echo "Backup kjører allerede: $pid" + if ps -p "$existing_pid"; then + echo "Backup kjører allerede: $existing_pid" exit 1 fi echo "Forrige backup ble avbrutt, rydder opp..." rm "$lockfile" - zfs snapshot -r "principal/backupz@avbrutt_${snapshot}" && \ + zfs snapshot -r "principal/backupz@avbrutt_${snapshot_date}" && \ echo "ZFS-snapshot OK." || echo "ZFS-snapshot FEILET!" # TODO: zfs rollback til forrige komplette backup. @@ -81,7 +80,7 @@ fi # Fang SIGINT, vi vil rydde opp om vi blir avbrutt. on_sigint() { - rm $lockfile + rm "$lockfile" echo 'Avbrutt, sletter låsfil...' exit 2 } @@ -117,7 +116,7 @@ while [ "$(zfs get -Hp available principal/backupz | cut -f3)" -lt 50000000000 ] done echo "Starter backup..." -echo "Snapshot ID: $snapshot" +echo "Snapshot ID: $snapshot_date" echo echo @@ -296,7 +295,7 @@ for host in "${hosts[@]}"; do declare -a command=( "$rsync" "${rsync_flags[@]}" - "--log-file=${logdir}/${host}.log.$snapshot" + "--log-file=${logdir}/${host}.log.$snapshot_date" ) declare exclude_paths_var="${host}_excludes[@]" @@ -323,7 +322,7 @@ for host in "${hosts[@]}"; do command+=("/backupz/${hosts_output_dir[$host]:-$host}/") echo "Starter backup for vert: $host" - "${command[@]}" >"${logdir}/${host}.out.$snapshot" 2>&1 & + "${command[@]}" >"${logdir}/${host}.out.$snapshot_date" 2>&1 & venteproc[$!]="$host" echo "Startet $!: ${command[*]}" done @@ -360,7 +359,7 @@ 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_date}" && \ echo "ZFS-snapshot ferdig." || echo "ZFS-snapshot FEILET!" echo echo Ledig plass: "$(zfs list -H -o avail principal/backupz)" -- 2.52.0 From 57b518b4f46c4a935a15927d8f1ce1c2fe39e7cf Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 16:36:27 +0900 Subject: [PATCH 08/19] backup.sh: flytt `ssh`-kommando inn i `rsync_flags` --- backup.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/backup.sh b/backup.sh index 7126b2d..d442ea8 100755 --- a/backup.sh +++ b/backup.sh @@ -263,19 +263,18 @@ declare -ra tom_excludes=( declare -ri start_time="$(date +%s)" -#export RSYNC_RSH="ssh -c arcfour -v" -export RSYNC_RSH="ssh -v" declare -r rsync="/usr/local/bin/rsync" declare -ra rsync_flags=( --archive --hard-links - --one-file-system --compress --delete --numeric-ids + --one-file-system + --relative + --rsh="ssh -v" --stats --inplace - --relative --exclude=/.zfs/ ) declare -r logdir="/backupz/log" -- 2.52.0 From 628efee5956325a78365c0dd1f8c2e0e1ecc158c Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 16:41:45 +0900 Subject: [PATCH 09/19] =?UTF-8?q?backup.sh:=20tell=20gjenst=C3=A5ende=20jo?= =?UTF-8?q?bber,=20nevn=20loggfiler=20n=C3=A5r=20det=20oppst=C3=A5r=20feil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/backup.sh b/backup.sh index d442ea8..90e2b51 100755 --- a/backup.sh +++ b/backup.sh @@ -331,17 +331,27 @@ echo "Rsync er i gang." # Vent til rsync er ferdig. echo "Venter til rsync er ferdig: ${!venteproc[*]}" +echo + while true; do wait -n -p pid; code=$? [[ -z "${pid}" ]] && break + if [ $code -eq 0 ]; then echo "${pid} (${venteproc["$pid"]:-???}): OK" else echo "${pid} (${venteproc["$pid"]:-???}): Rsync returnerte feil (${code})" + echo "Se loggfilene her for mer informasjon:" + echo "- ${logdir}/${venteproc["$pid"]}.log.$snapshot_date" + echo "- ${logdir}/${venteproc["$pid"]}.out.$snapshot_date" fi + + unset 'venteproc["$pid"]' + + echo "${#venteproc[@]} jobber gjenstår..." + echo done -echo echo "Rsync er ferdig." declare -ri end_time="$(date +%s)" -- 2.52.0 From d765976a36c8c78412b1dcb8adbd8689f389c68d Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 16:49:48 +0900 Subject: [PATCH 10/19] =?UTF-8?q?backup.sh:=20oppdater=20dokumentasjon=20o?= =?UTF-8?q?m=20nye=20bokser=20og=20ssh-n=C3=B8kler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/backup.sh b/backup.sh index 90e2b51..266868a 100755 --- a/backup.sh +++ b/backup.sh @@ -8,13 +8,14 @@ # Oppdatert av pederbs og yorinad 2017.02.04 # -# for å legge til en backup jobb: -# zfs create principal/backupz/%name% +# For å legge til en backup jobb, lag et nyt datasett under principal/backupz: # -#sørg for at principal kan logge inn som brukerene på boksen uten passord: -# -#ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsCm6f5JOlKDbZMiQ6rXvU35QU4Gs/WKKlZymXtFxPhK5jBoZskQjNhfsr+peuhnZ1y+04L9qEBkN3jN0ThROaRaKSFVWfnMnij7pEB0bmJRxDmkQsHL7YsAm6tPn8116tt9m9ASPYE5RpnaDGtxTP7uXa42URvwXdvWY618tdX4z39JG9f85KYexhwRbhaBMLnSPH6JKCKu1tTBwr7oEbuhLFrFXQwqWRip/oN/6/eSxnIrwaey1GM+CdNfeGh/0OeQJ4XIUas2WbgiQRw6Dkxo32FeFS5LVaOYWRys6W3Znw9a9yOYImjJ8WUmiwSeN2bksUizNBNA1HBhoKGM5b root@alphys +# zfs create principal/backupz/%name% # +# Sørg for at principal kan logge inn som brukerene på boksen uten passord. +# Det ligger et skript for å lage nye nøkkelpar ved './ssh_extra_keys/generate_keypair.sh', +# men du kan alternativt bruke nøkkelen som ligger i '~/.ssh/id_ed25519.pub'. +# I førstnevnte tilfelle må du også registrere boksen i './ssh_config_backup_targets'. declare -ra required_tools=( rsync -- 2.52.0 From 978f87134153080ec63c4de496d9f4aebedd714d Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 16:59:40 +0900 Subject: [PATCH 11/19] backup.sh: sjekk at backup-kataloger har tilsvarende monterte datasett --- backup.sh | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/backup.sh b/backup.sh index 266868a..75ae4a6 100755 --- a/backup.sh +++ b/backup.sh @@ -262,6 +262,36 @@ declare -ra tom_excludes=( ) ### Slutt på liste over vertsmaskiner og hva som skal tas backup av. ### +# Sjekk at alle backup-kataloger har tilhørende datasett, og at datasettene er montert +for host in "${hosts[@]}"; do + declare katalog="/backupz/${hosts_output_dir[$host]:-$host}" + declare dataset="principal/backupz/${hosts_output_dir[$host]:-$host}" + + # Sjekk at ZFS-datasettet finnes + if ! zfs list "$dataset" >/dev/null 2>&1; then + echo "Feil: ZFS-datasettet '$dataset' finnes ikke. Opprett det med: zfs create $dataset" >&2 + rm "$lockfile" + exit 1 + fi + + if [ ! -d "$katalog" ]; then + echo "Feil: katalogen '$katalog' finnes ikke. Opprett den med: mkdir '$katalog'" >&2 + rm "$lockfile" + exit 1 + fi + + # Sjekk at datasettet er montert, og forsøk å mounte om nødvendig + declare mounted_val="$(zfs get -H -o value mounted "$dataset" 2>/dev/null || echo "no")" + if [ "${mounted_val:-no}" != "yes" ]; then + echo "Datasettet '$dataset' er ikke montert på '$katalog'. Forsøker å mounte..." + if ! zfs mount "$dataset" >/dev/null 2>&1; then + echo "Kunne ikke mounte '$dataset'. Avbryter." >&2 + rm "$lockfile" + exit 1 + fi + fi +done + declare -ri start_time="$(date +%s)" declare -r rsync="/usr/local/bin/rsync" -- 2.52.0 From 7c54deef99d93f30c9d610b6fe80357a4f41dab9 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 17:13:45 +0900 Subject: [PATCH 12/19] backup.sh: litt penere printing av rsync kommandoer --- backup.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/backup.sh b/backup.sh index 75ae4a6..2678785 100755 --- a/backup.sh +++ b/backup.sh @@ -119,7 +119,6 @@ done echo "Starter backup..." echo "Snapshot ID: $snapshot_date" echo -echo ### Liste over vertsmaskiner og hva som skal tas backup av. ### @@ -321,6 +320,8 @@ declare -A venteproc=() # rsync_flags="${rsync_flags[@]} --checksum" # fi +echo "Starter rsync for følgende verter: ${hosts[*]}" +echo for host in "${hosts[@]}"; do declare -a command=( "$rsync" @@ -354,10 +355,14 @@ for host in "${hosts[@]}"; do echo "Starter backup for vert: $host" "${command[@]}" >"${logdir}/${host}.out.$snapshot_date" 2>&1 & venteproc[$!]="$host" - echo "Startet $!: ${command[*]}" + echo "Startet $!:" + echo "${command[0]} \\" + for ((i=1; i<${#command[@]}-1; i++)); do + echo " ${command[i]} \\" + done + echo " ${command[-1]}" + echo done - -echo echo "Rsync er i gang." # Vent til rsync er ferdig. -- 2.52.0 From a90755bdd7fcd8a41ab45743ba7b0613316cd548 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 17:25:07 +0900 Subject: [PATCH 13/19] backup.sh: ikke print alle standard-flaggene for rsync-kommando --- backup.sh | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/backup.sh b/backup.sh index 2678785..a271d75 100755 --- a/backup.sh +++ b/backup.sh @@ -17,6 +17,8 @@ # men du kan alternativt bruke nøkkelen som ligger i '~/.ssh/id_ed25519.pub'. # I førstnevnte tilfelle må du også registrere boksen i './ssh_config_backup_targets'. + +# === Sjekk at nødvendige verktøy er installert. === declare -ra required_tools=( rsync ssh @@ -47,6 +49,8 @@ if [ \ exit 1 fi +# === Start === + echo "PVV; hjemmelaget backupscript (\$ git commit sha: $(cd /backupz && git rev-parse HEAD) \$)" echo date @@ -57,8 +61,8 @@ if [ "$1" = "full" ]; then # Fullbackupen starter før midnatt, legg på en dag declare -r snapshot_date=$(date -v +1d +%Y%m%d) fi +# Sjekk om en annen backup kjører eller om forrige backup ble avbrutt. declare -r lockfile="/backupz/backup.sh.lock" - if [ -e $lockfile ]; then declare -r existing_pid="$(cat $lockfile)" @@ -92,8 +96,10 @@ 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 +# Dette tilsvarer 50 GB, juster etter behov. +declare -r min_free_space=50000000000 + +while [ "$(zfs get -Hp available principal/backupz | cut -f3)" -lt "$min_free_space" ] ; do echo; echo "Disken er nesten full, rydder"; echo @@ -309,17 +315,8 @@ declare -ra rsync_flags=( ) 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 - echo "Starter rsync for følgende verter: ${hosts[*]}" echo for host in "${hosts[@]}"; do @@ -357,7 +354,10 @@ for host in "${hosts[@]}"; do venteproc[$!]="$host" echo "Startet $!:" echo "${command[0]} \\" - for ((i=1; i<${#command[@]}-1; i++)); do + # Ikke print de første rsync-flagga i kommandoen + echo " # ...standard rsync-flagg... \\" + declare -i start_index=$((1 + ${#rsync_flags[@]})) + for ((i="$start_index"; i<${#command[@]}-1; i++)); do echo " ${command[i]} \\" done echo " ${command[-1]}" @@ -365,7 +365,6 @@ for host in "${hosts[@]}"; do done echo "Rsync er i gang." -# Vent til rsync er ferdig. echo "Venter til rsync er ferdig: ${!venteproc[*]}" echo @@ -394,16 +393,10 @@ declare -ri end_time="$(date +%s)" declare -ri elapsed_time="$((end_time - start_time))" printf 'Tid brukt på rsync: %03d:%02d:%02d\n' $((elapsed_time/3600)) $(((elapsed_time/60)%60)) $((elapsed_time%60)) -# Behoeves ikke da principal ikke har almen brukerinnlogging. -# # Gjør hjemmemappene lesbare bare for brukeren. -# find /backupz/homepvv/export/home/pvv -maxdepth 2 -mindepth 2 -exec chmod 700 {} \; - # Touch home slik at timestamp på snapshot blir når backup var ferdig. touch /backupz/homepvv/export/home -# Ta et zfs snapshot echo "Tar ZFS-snapshot..." - zfs snapshot -r "principal/backupz@${snapshot_date}" && \ echo "ZFS-snapshot ferdig." || echo "ZFS-snapshot FEILET!" echo -- 2.52.0 From dd003f6b8d093d321bec7ac75bd0faf2f2e5dad6 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 17:33:36 +0900 Subject: [PATCH 14/19] backup.sh: del opp skriptet i seksjoner --- backup.sh | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/backup.sh b/backup.sh index a271d75..e23ae59 100755 --- a/backup.sh +++ b/backup.sh @@ -18,7 +18,12 @@ # I førstnevnte tilfelle må du også registrere boksen i './ssh_config_backup_targets'. +echo "PVV; hjemmelaget backupscript (\$ git commit sha: $(cd /backupz && git rev-parse HEAD) \$)" +echo +date + # === Sjekk at nødvendige verktøy er installert. === + declare -ra required_tools=( rsync ssh @@ -49,11 +54,8 @@ if [ \ exit 1 fi -# === Start === -echo "PVV; hjemmelaget backupscript (\$ git commit sha: $(cd /backupz && git rev-parse HEAD) \$)" -echo -date +# === Sjekk for pågående backup eller avbrutt backup, sett låsfil og signalhåndtering. === # Blir brukt som navn på ZFS-snapshot og logger. declare -r snapshot_date="$(date +%Y%m%d)" @@ -93,12 +95,14 @@ trap on_sigint SIGINT echo "$$" > "$lockfile" + +# === Rydd opp gamle backups hvis det trengs plass. === + echo "Sjekker at det er nok ledig plass på disken..." zfs get available principal/backupz # Dette tilsvarer 50 GB, juster etter behov. declare -r min_free_space=50000000000 - while [ "$(zfs get -Hp available principal/backupz | cut -f3)" -lt "$min_free_space" ] ; do echo; echo "Disken er nesten full, rydder"; @@ -122,11 +126,8 @@ while [ "$(zfs get -Hp available principal/backupz | cut -f3)" -lt "$min_free_sp echo done -echo "Starter backup..." -echo "Snapshot ID: $snapshot_date" -echo -### Liste over vertsmaskiner og hva som skal tas backup av. ### +# === Liste over vertsmaskiner og hva som skal tas backup av. === # TODO: kanskje noe av dette enklere kunne blitt uttrykt # med en egen json-fil og litt jq-magi? @@ -265,9 +266,10 @@ declare -ra tom_includes=( declare -ra tom_excludes=( "/var/cache/" ) -### Slutt på liste over vertsmaskiner og hva som skal tas backup av. ### -# Sjekk at alle backup-kataloger har tilhørende datasett, og at datasettene er montert + +# === Sjekk at alle backup-kataloger har tilhørende datasett, og at datasettene er montert. === + for host in "${hosts[@]}"; do declare katalog="/backupz/${hosts_output_dir[$host]:-$host}" declare dataset="principal/backupz/${hosts_output_dir[$host]:-$host}" @@ -297,8 +299,14 @@ for host in "${hosts[@]}"; do fi done -declare -ri start_time="$(date +%s)" +# === Start rsync-jobber === + +echo "Starter backup..." +echo "Snapshot ID: $snapshot_date" +echo + +declare -ri start_time="$(date +%s)" declare -r rsync="/usr/local/bin/rsync" declare -ra rsync_flags=( --archive @@ -314,7 +322,6 @@ declare -ra rsync_flags=( --exclude=/.zfs/ ) declare -r logdir="/backupz/log" - declare -A venteproc=() echo "Starter rsync for følgende verter: ${hosts[*]}" @@ -365,9 +372,11 @@ for host in "${hosts[@]}"; do done echo "Rsync er i gang." + +# === Vent på at alle rsync-jobbene skal bli ferdige === + echo "Venter til rsync er ferdig: ${!venteproc[*]}" echo - while true; do wait -n -p pid; code=$? [[ -z "${pid}" ]] && break @@ -386,9 +395,11 @@ while true; do echo "${#venteproc[@]} jobber gjenstår..." echo done - echo "Rsync er ferdig." + +# === Oppsummering, ta ZFS-snapshot og avslutt === + declare -ri end_time="$(date +%s)" declare -ri elapsed_time="$((end_time - start_time))" printf 'Tid brukt på rsync: %03d:%02d:%02d\n' $((elapsed_time/3600)) $(((elapsed_time/60)%60)) $((elapsed_time%60)) -- 2.52.0 From 49faba4353cd8e368cad3e8823cea6a9d5c1e42d Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 18:01:26 +0900 Subject: [PATCH 15/19] backup.sh: fjern gamle utkommenterte verter --- backup.sh | 68 ------------------------------------------------------- 1 file changed, 68 deletions(-) diff --git a/backup.sh b/backup.sh index e23ae59..def04d2 100755 --- a/backup.sh +++ b/backup.sh @@ -153,56 +153,6 @@ declare -ra ameno_excludes=( "/var/log/journal/" ) -# knakelibrak (wiki) -# hosts+=("knakelibrak_wiki") -# host_ssh_hostname["knakelibrak_wiki"]="wiki" -# hosts_output_dir["knakelibrak_wiki"]="wiki" -# declare -ra wiki_includes=( -# "/var/lib/mediawiki" -# ) -# declare -ra wiki_excludes=() - -# knakelibrak (databases) -# hosts+=("knakelibrak_databases") -# host_ssh_hostname["knakelibrak_databases"]="knakelibrak" -# hosts_output_dir["knakelibrak_databases"]="databases" -# declare -ra knakelibrak_databases_includes=( -# "/var/backups/databases" -# ) -# declare -ra knakelibrak_databases_excludes=() - -# jokum (synapse) -# hosts+=("jokum_synapse") -# host_ssh_hostname["jokum_synapse"]="jokum" -# hosts_output_dir["jokum_synapse"]="jokum/synapse" -# declare -ra jokum_synapse_includes=( -# "/data/synapse/" -# ) -# declare -ra jokum_synapse_excludes=() - -# skrotnisse -# hosts+=("skrotnisse") -# declare -ra skrotnisse_includes=( -# "/var/www/" -# "/srv/" -# ) -# declare -ra skrotnisse_excludes=() - -# dash8 -# hosts+=("dash8") -# declare -ra dash8_includes=( -# "/var/lib/bitlbee/" -# ) -# declare -ra dash8_excludes=() - -# tim -# hosts+=("tim") -# hosts_output_dir["tim"]="web" -# declare -ra tim_includes=( -# "/var/lib/squirrelmail" -# ) -# declare -ra tim_excludes=() - # microbel (hjemmeområder) hosts+=("homepvv") declare -ra homepvv_includes=( @@ -229,15 +179,6 @@ declare -ra innovation_excludes=( "/var/db/freebsd-update/files/" ) -# lommel -# hosts+=("lommel") -# declare -ra lommel_includes=( -# "/" -# ) -# declare -ra lommel_excludes=( - # se ./lommel.exclude - den skal bli plukket opp automatisk -# ) - # sleipner hosts+=("sleipner") declare -ra sleipner_includes=( @@ -248,15 +189,6 @@ declare -ra sleipner_excludes=( "/var/cache/" ) -# spikkjeposche -# hosts+=("spikkjeposche") -# declare -ra spikkjeposche_includes=( -# "/usr/local/www" -# "/usr/local/etc/lighttpd" -# "/etc/ssl/private" -# ) -# declare -ra spikkjeposche_excludes=() - # tom hosts+=("tom") declare -ra tom_includes=( -- 2.52.0 From 75b2c7395cba1f9505f823480f9ff0065e7b44a1 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 18:11:27 +0900 Subject: [PATCH 16/19] =?UTF-8?q?backup.sh:=20bli=20kvitt=20litt=20`declar?= =?UTF-8?q?e`=20st=C3=B8y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 76 +++++++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/backup.sh b/backup.sh index def04d2..e391872 100755 --- a/backup.sh +++ b/backup.sh @@ -24,7 +24,7 @@ date # === Sjekk at nødvendige verktøy er installert. === -declare -ra required_tools=( +required_tools=( rsync ssh zfs @@ -44,8 +44,8 @@ if [ "$(id -u)" -ne 0 ]; then fi # 5.1 er minimum pga. wait '-p' flagget. -declare -r minimum_bash_major_version="5" -declare -r minimum_bash_minor_version="1" +minimum_bash_major_version="5" +minimum_bash_minor_version="1" if [ \ "${BASH_VERSINFO[0]}" -lt "$minimum_bash_major_version" ] || \ { [ "${BASH_VERSINFO[0]}" -eq "$minimum_bash_major_version" ] && \ @@ -58,15 +58,15 @@ fi # === Sjekk for pågående backup eller avbrutt backup, sett låsfil og signalhåndtering. === # Blir brukt som navn på ZFS-snapshot og logger. -declare -r snapshot_date="$(date +%Y%m%d)" +snapshot_date="$(date +%Y%m%d)" if [ "$1" = "full" ]; then # Fullbackupen starter før midnatt, legg på en dag - declare -r snapshot_date=$(date -v +1d +%Y%m%d) + snapshot_date=$(date -v +1d +%Y%m%d) fi # Sjekk om en annen backup kjører eller om forrige backup ble avbrutt. -declare -r lockfile="/backupz/backup.sh.lock" +lockfile="/backupz/backup.sh.lock" if [ -e $lockfile ]; then - declare -r existing_pid="$(cat $lockfile)" + existing_pid="$(cat $lockfile)" # TODO: Bruk bedre metode for å finne prosess. if ps -p "$existing_pid"; then @@ -102,13 +102,13 @@ echo "Sjekker at det er nok ledig plass på disken..." zfs get available principal/backupz # Dette tilsvarer 50 GB, juster etter behov. -declare -r min_free_space=50000000000 +min_free_space=50000000000 while [ "$(zfs get -Hp available principal/backupz | cut -f3)" -lt "$min_free_space" ] ; do echo; echo "Disken er nesten full, rydder"; echo - declare -ri min_backups=5 + min_backups=5 if [ "$(zfs list -t snapshot | grep -c "backupz@")" -lt "$min_backups" ]; then echo; echo "Mindre enn $min_backups backups lagret, feiger ut fra sletting"; @@ -116,10 +116,10 @@ while [ "$(zfs get -Hp available principal/backupz | cut -f3)" -lt "$min_free_sp break; fi - declare -r oldest=$(zfs list -t snapshot | grep backupz@ | head -n1 | tr @ ' ' | awk '{print $2}') - echo "Kjører zfs destroy på alle disker @$oldest" + oldest_snapshot=$(zfs list -t snapshot | grep backupz@ | head -n1 | tr @ ' ' | awk '{print $2}') + echo "Kjører zfs destroy på alle disker @$oldest_snapshot" for d in $(zfs list | grep ^principal/backupz | awk '{print $1}'); do - zfs destroy "$d@$oldest" + zfs destroy "$d@$oldest_snapshot" done zfs get available principal/backupz @@ -143,11 +143,11 @@ declare -A hosts_output_dir=() # ameno hosts+=("ameno") -declare -ra ameno_includes=( +ameno_includes=( "/" "/boot/firmware" ) -declare -ra ameno_excludes=( +ameno_excludes=( "/var/cache/" "/var/lib/snapd/" "/var/log/journal/" @@ -155,13 +155,13 @@ declare -ra ameno_excludes=( # microbel (hjemmeområder) hosts+=("homepvv") -declare -ra homepvv_includes=( +homepvv_includes=( "/" "/boot" "/export/home/pvv" "/var" ) -declare -ra homepvv_excludes=( +homepvv_excludes=( # Se ./homepvv.exclude - den skal bli plukket opp automatisk ) @@ -169,11 +169,11 @@ declare -ra homepvv_excludes=( # Minecraft-verden kopieres fra /var/backups/minecraft/current/ istf. # /srv/minecraft-pvv/. hosts+=("innovation") -declare -ra innovation_includes=( +innovation_includes=( "/" "/boot/efi" ) -declare -ra innovation_excludes=( +innovation_excludes=( "/srv/minecraft-pvv/" "/var/cache/" "/var/db/freebsd-update/files/" @@ -181,21 +181,21 @@ declare -ra innovation_excludes=( # sleipner hosts+=("sleipner") -declare -ra sleipner_includes=( +sleipner_includes=( "/" ) -declare -ra sleipner_excludes=( +sleipner_excludes=( "/scratch/" "/var/cache/" ) # tom hosts+=("tom") -declare -ra tom_includes=( +tom_includes=( "/" "/boot/efi" ) -declare -ra tom_excludes=( +tom_excludes=( "/var/cache/" ) @@ -203,8 +203,8 @@ declare -ra tom_excludes=( # === Sjekk at alle backup-kataloger har tilhørende datasett, og at datasettene er montert. === for host in "${hosts[@]}"; do - declare katalog="/backupz/${hosts_output_dir[$host]:-$host}" - declare dataset="principal/backupz/${hosts_output_dir[$host]:-$host}" + katalog="/backupz/${hosts_output_dir[$host]:-$host}" + dataset="principal/backupz/${hosts_output_dir[$host]:-$host}" # Sjekk at ZFS-datasettet finnes if ! zfs list "$dataset" >/dev/null 2>&1; then @@ -220,8 +220,8 @@ for host in "${hosts[@]}"; do fi # Sjekk at datasettet er montert, og forsøk å mounte om nødvendig - declare mounted_val="$(zfs get -H -o value mounted "$dataset" 2>/dev/null || echo "no")" - if [ "${mounted_val:-no}" != "yes" ]; then + is_mounted="$(zfs get -H -o value mounted "$dataset" 2>/dev/null || echo "no")" + if [ "${is_mounted:-no}" != "yes" ]; then echo "Datasettet '$dataset' er ikke montert på '$katalog'. Forsøker å mounte..." if ! zfs mount "$dataset" >/dev/null 2>&1; then echo "Kunne ikke mounte '$dataset'. Avbryter." >&2 @@ -238,9 +238,9 @@ echo "Starter backup..." echo "Snapshot ID: $snapshot_date" echo -declare -ri start_time="$(date +%s)" -declare -r rsync="/usr/local/bin/rsync" -declare -ra rsync_flags=( +start_time="$(date +%s)" +rsync="/usr/local/bin/rsync" +rsync_flags=( --archive --hard-links --compress @@ -253,20 +253,20 @@ declare -ra rsync_flags=( --inplace --exclude=/.zfs/ ) -declare -r logdir="/backupz/log" +logdir="/backupz/log" declare -A venteproc=() echo "Starter rsync for følgende verter: ${hosts[*]}" echo for host in "${hosts[@]}"; do - declare -a command=( + command=( "$rsync" "${rsync_flags[@]}" "--log-file=${logdir}/${host}.log.$snapshot_date" ) - declare exclude_paths_var="${host}_excludes[@]" - declare -a exclude_paths=("${!exclude_paths_var}") + exclude_paths_var="${host}_excludes[@]" + exclude_paths=("${!exclude_paths_var}") for exclude in "${exclude_paths[@]}"; do command+=("--exclude=${exclude}") done @@ -275,8 +275,8 @@ for host in "${hosts[@]}"; do command+=("--exclude-from=/backupz/${host}.exclude") fi - declare include_paths_var="${host}_includes[@]" - declare -a include_paths=("${!include_paths_var}") + 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 @@ -295,7 +295,7 @@ for host in "${hosts[@]}"; do echo "${command[0]} \\" # Ikke print de første rsync-flagga i kommandoen echo " # ...standard rsync-flagg... \\" - declare -i start_index=$((1 + ${#rsync_flags[@]})) + start_index="$((1 + ${#rsync_flags[@]}))" for ((i="$start_index"; i<${#command[@]}-1; i++)); do echo " ${command[i]} \\" done @@ -332,8 +332,8 @@ echo "Rsync er ferdig." # === Oppsummering, ta ZFS-snapshot og avslutt === -declare -ri end_time="$(date +%s)" -declare -ri elapsed_time="$((end_time - start_time))" +end_time="$(date +%s)" +elapsed_time="$((end_time - start_time))" printf 'Tid brukt på rsync: %03d:%02d:%02d\n' $((elapsed_time/3600)) $(((elapsed_time/60)%60)) $((elapsed_time%60)) # Touch home slik at timestamp på snapshot blir når backup var ferdig. -- 2.52.0 From ed9c7849c7aca0e9540646194e0af08b1cfea357 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 28 Jan 2026 18:14:04 +0900 Subject: [PATCH 17/19] =?UTF-8?q?backup.sh:=20se=20etter=20git=20f=C3=B8r?= =?UTF-8?q?=20vi=20kj=C3=B8rer=20git?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backup.sh b/backup.sh index e391872..8fa2839 100755 --- a/backup.sh +++ b/backup.sh @@ -18,7 +18,11 @@ # I førstnevnte tilfelle må du også registrere boksen i './ssh_config_backup_targets'. -echo "PVV; hjemmelaget backupscript (\$ git commit sha: $(cd /backupz && git rev-parse HEAD) \$)" +if ! command -v git >/dev/null 2>&1; then + echo "PVV; hjemmelaget backupscript (\$ git commit sha: ??? \$)" +else + echo "PVV; hjemmelaget backupscript (\$ git commit sha: $(cd /backupz && git rev-parse HEAD) \$)" +fi echo date -- 2.52.0 From 0d513a38bf4d8bd350beb1dd263252301464a768 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Thu, 29 Jan 2026 14:43:52 +0900 Subject: [PATCH 18/19] =?UTF-8?q?backup.sh:=20h=C3=A5ndter=20manglende=20e?= =?UTF-8?q?ksluderingsliste?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/backup.sh b/backup.sh index 8fa2839..5fb1581 100755 --- a/backup.sh +++ b/backup.sh @@ -269,27 +269,31 @@ for host in "${hosts[@]}"; do "--log-file=${logdir}/${host}.log.$snapshot_date" ) - exclude_paths_var="${host}_excludes[@]" - exclude_paths=("${!exclude_paths_var}") - for exclude in "${exclude_paths[@]}"; do - command+=("--exclude=${exclude}") - done + exclude_array_name="${host}_excludes" + if declare -p "$exclude_array_name" >/dev/null 2>&1; then + exclude_paths_var="${host}_excludes[@]" + exclude_paths=( "${!exclude_paths_var}" ) + for exclude in "${exclude_paths[@]}"; do + command+=( "--exclude=${exclude}" ) + done + fi 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 + include_array_name="${host}_includes" + if declare -p "$include_array_name" >/dev/null 2>&1; then + include_paths_var="${host}_includes[@]" + include_paths=( "${!include_paths_var}" ) + for include in "${include_paths[@]}"; do + command+=("${host_ssh_hostname[$host]:-$host}:$include") + done + else 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" -- 2.52.0 From dd55c182fb7121d5d56256cee96c728516e9ae66 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Thu, 29 Jan 2026 14:44:16 +0900 Subject: [PATCH 19/19] =?UTF-8?q?backup.sh:=20h=C3=A5ndter=20ekstra=20rsyn?= =?UTF-8?q?c=20argumenter=20per=20vert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/backup.sh b/backup.sh index 5fb1581..763e8b7 100755 --- a/backup.sh +++ b/backup.sh @@ -269,6 +269,15 @@ for host in "${hosts[@]}"; do "--log-file=${logdir}/${host}.log.$snapshot_date" ) + extra_array_name="${host}_extra_rsync_flags" + if declare -p "$extra_array_name" >/dev/null 2>&1; then + extra_rsync_flags_var="${host}_extra_rsync_flags[@]" + extra_rsync_flags=( "${!extra_rsync_flags_var}" ) + for ef in "${extra_rsync_flags[@]}"; do + command+=( "$ef" ) + done + fi + exclude_array_name="${host}_excludes" if declare -p "$exclude_array_name" >/dev/null 2>&1; then exclude_paths_var="${host}_excludes[@]" -- 2.52.0