368 lines
8.9 KiB
Bash
Executable File
368 lines
8.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
|
|
#
|
|
|
|
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
|
|
date
|
|
|
|
|
|
# Blir brukt som navn på ZFS-snapshot og logger.
|
|
declare -r snapshot="$(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)
|
|
fi
|
|
|
|
declare -r lockfile="/backupz/backup.sh.lock"
|
|
|
|
if [ -e $lockfile ]; then
|
|
declare -r 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
|
|
|
|
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";
|
|
echo
|
|
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"
|
|
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 -a 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=()
|
|
|
|
# ameno
|
|
hosts+=("ameno")
|
|
declare -ra ameno_includes=(
|
|
"/"
|
|
"/boot/firmware"
|
|
)
|
|
declare -ra 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 -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=(
|
|
"/"
|
|
"/boot"
|
|
"/export/home/pvv"
|
|
"/var"
|
|
)
|
|
declare -ra 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 -ra innovation_includes=(
|
|
"/"
|
|
"/boot/efi"
|
|
)
|
|
declare -ra innovation_excludes=(
|
|
"/srv/minecraft-pvv/"
|
|
"/var/cache/"
|
|
"/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=(
|
|
"/"
|
|
)
|
|
declare -ra sleipner_excludes=(
|
|
"/scratch/"
|
|
"/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=(
|
|
"/"
|
|
"/boot/efi"
|
|
)
|
|
declare -ra 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"
|
|
declare -ra 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
|
|
declare -a command=(
|
|
"$rsync"
|
|
"${rsync_flags[@]}"
|
|
"--log-file=${logdir}/${host}.log.$snapshot"
|
|
)
|
|
|
|
declare exclude_paths_var="${host}_excludes[@]"
|
|
declare -a 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
|
|
|
|
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
|
|
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[$!]="$host"
|
|
echo "Startet $!: ${command[*]}"
|
|
done
|
|
|
|
echo
|
|
echo "Rsync er i gang."
|
|
|
|
# Vent til rsync er ferdig.
|
|
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} (${venteproc["$pid"]:-???}): OK"
|
|
else
|
|
echo "${pid} (${venteproc["$pid"]:-???}): Rsync returnerte feil (${code})"
|
|
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
|