Files
principal-backup-script/backup.sh
2026-01-30 03:15:43 +09:00

333 lines
7.9 KiB
Bash
Executable File

#!/usr/local/bin/bash
#
# Hjemmesnekret script som tar backup av PVV-servere.
#
# orjane - 2008.11.10
#
# Oppdatert av pederbs og yorinad 2017.02.04
#
# 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:
#
#ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsCm6f5JOlKDbZMiQ6rXvU35QU4Gs/WKKlZymXtFxPhK5jBoZskQjNhfsr+peuhnZ1y+04L9qEBkN3jN0ThROaRaKSFVWfnMnij7pEB0bmJRxDmkQsHL7YsAm6tPn8116tt9m9ASPYE5RpnaDGtxTP7uXa42URvwXdvWY618tdX4z39JG9f85KYexhwRbhaBMLnSPH6JKCKu1tTBwr7oEbuhLFrFXQwqWRip/oN/6/eSxnIrwaey1GM+CdNfeGh/0OeQJ4XIUas2WbgiQRw6Dkxo32FeFS5LVaOYWRys6W3Znw9a9yOYImjJ8WUmiwSeN2bksUizNBNA1HBhoKGM5b root@alphys
#
echo "PVV; hjemmelaget backupscript (\$ git commit sha: $(cd /backupz && git rev-parse HEAD) \$)"
echo
date
# Blir brukt som navn på ZFS-snapshot og logger.
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"
if [ -e $lockfile ]; then
pid="$(cat $lockfile)"
# TODO: Bruk bedre metode for å finne prosess.
if ps -p "$pid"; then
echo "Backup kjører allerede: $pid"
exit 1
fi
echo "Forrige backup ble avbrutt, rydder opp..."
rm "$lockfile"
zfs snapshot -r "principal/backupz@avbrutt_${snapshot}" && \
echo "ZFS-snapshot OK." || echo "ZFS-snapshot FEILET!"
# TODO: zfs rollback til forrige komplette backup.
echo "Ferdig med oppryddingen."
fi
# Fang SIGINT, vi vil rydde opp om vi blir avbrutt.
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
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";
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..."
echo "Snapshot ID: $snapshot"
echo
echo
### 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?
# Liste over vertsmaskiner som skal tas backup av.
declare hosts=()
# SSH-vertsnavn hvis det er forskjellig fra vertsnavnet i listen.
declare -A host_ssh_hostname=()
# Backup-katalog hvis den er forskjellig fra vertsnavnet i listen.
declare -A hosts_output_dir=()
hosts+=("ameno")
declare -r ameno_includes=(
"/"
"/boot/firmware"
)
declare -r ameno_excludes=(
"/var/cache/"
"/var/lib/snapd/"
"/var/log/journal/"
)
# 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=()
# 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=()
# 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/.
hosts+=("innovation")
declare -r innovation_includes=(
"/"
"/boot/efi"
)
declare -r innovation_excludes=(
"/srv/minecraft-pvv/"
"/var/cache/"
"/var/db/freebsd-update/files/"
)
# hosts+=("lommel")
# declare -r lommel_includes=(
# "/"
# )
# declare -r lommel_excludes=(
# se ./lommel.exclude - den skal bli plukket opp automatisk
# )
hosts+=("sleipner")
declare -r sleipner_includes=(
"/"
)
declare -r sleipner_excludes=(
"/scratch/"
"/var/cache/"
)
# hosts+=("spikkjeposche")
# declare -r spikkjeposche_includes=(
# "/usr/local/www"
# "/usr/local/etc/lighttpd"
# "/etc/ssl/private"
# )
# declare -r spikkjeposche_excludes=()
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
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 pid in "${venteproc[@]}" ; do
wait "$pid"
feilkode=$?
if [ $feilkode -eq 0 ]; then
echo "$pid: OK"
else
echo "$pid: Rsync returnerte feil (${feilkode})."
fi
done
echo
echo "Rsync er ferdig."
# 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}" && \
echo "ZFS-snapshot ferdig." || echo "ZFS-snapshot FEILET!"
echo
echo Ledig plass: "$(zfs list -H -o avail principal/backupz)"
echo
# TODO: Slett enkelte gamle snapshots?
echo "Backup ferdig: $(date)"
rm "$lockfile"
zpool status -xv principal