nutools/ubackup

191 lines
6.3 KiB
Bash
Executable File

#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname -- "$0")/lib/ulib/auto" || exit 1
function display_help() {
uecho "$scriptname: faire une sauvegarde des fichiers
USAGE
$scriptname [options]
OPTIONS
-l Lister les profils de sauvegarde disponibles.
-p Spécifier le profil de sauvegarde à effectuer. Par défaut, toutes les
sauvegardes sont effectuées.
-u USER
Faire le sauvegarde pour l'utilisateur \$USER. Cette option n'est valide
que pour l'utilisateur root.
-n Afficher ce qui doit être fait plutôt que de le faire
-H Arrêter la machine après une sauvegarde REUSSIE."
}
action=getargs
profile=
HOMEDIR="$HOME"
fake_maybe=
halt=
lockfile="$TMPDIR/ubackup.lock"
parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with display_help' \
-l,--list action=list \
-p:,--profile: profile= \
-u:,--user: user= \
-n,--fake fake_maybe=echo \
-H,--halt halt=1 \
--backup action=backup \
--lockfile: lockfile= \
@ args -- "$@" && set -- "${args[@]}" || die "$args"
if [ -n "$user" ]; then
if is_root; then
eval "HOMEDIR=~$user"
else
die "L'option -u n'est supportée que pour l'utilisateur root"
fi
fi
function __set_defaults() {
local HOME="$HOMEDIR"
set_defaults ubackup
}
__set_defaults
if [ "$action" == "list" ]; then
echo "${BACKUPS[*]}"
exit 0
elif [ "$action" == "getargs" ]; then
# mettre un verrou pour empêcher les opérations de sauvegarde simultanées
if [ -f "$lockfile" ]; then
if [ "$(<"$lockfile")" != "$$" ]; then
die "Une sauvegarde est en cours. Impossible de continuer.
Si ce message est erroné, supprimez manuellement $lockfile"
fi
fi
# n'installer le trap de cleanup qu'après avoir testé qu'une sauvegarde n'était pas en cours.
autoclean "$lockfile"
echo "$$" >"$lockfile"
# arguments pour la sauvegarde
args=()
if [ -n "$profile" ]; then
backups=("$profile")
else
backups=("${BACKUPS[@]}")
fi
for backup in "${backups[@]}"; do
if [ "$backup" == "DEFAULT" ]; then
backup=
fi
destdir="${backup:+${backup}_}DESTDIR"; destdir="${!destdir}"
vgname="${backup:+${backup}_}VGNAME"; vgname="${!vgname}"
lvname="${backup:+${backup}_}LVNAME"; lvname="${!lvname}"
configdir="${backup:+${backup}_}CONFIGDIR"; configdir="${!configdir:-$HOMEDIR/etc}"
includes="${backup:+${backup}_}INCLUDES"; includes="${!includes}"
excludes="${backup:+${backup}_}EXCLUDES"; excludes="${!excludes}"
script="${backup:+${backup}_}SCRIPT"; script="${!script}"
mount="${backup:+${backup}_}MOUNT"; mount="${!mount:-$scriptdir/lib/backup.mount}"
umount="${backup:+${backup}_}UMOUNT"; umount="${!umount:-$scriptdir/lib/backup.umount}"
destdir="$(abspath "$destdir" "$configdir")"
[ -d "$destdir" ] || die "$destdir: répertoire de sauvegarde inexistant"
configdir="$(abspath "$configdir")"
[ -n "$includes" ] && includes="$(abspath "$includes" "$configdir")"
[ -f "$includes" ] || die "$(ppath "$includes"): liste des fichiers à inclure inexistante"
[ -n "$excludes" ] && excludes="$(abspath "$excludes" "$configdir")"
[ -n "$script" ] && script="$(abspath "$script" "$configdir")"
[ -n "$mount" ] && mount="$(abspath "$mount" "$configdir")"
[ -n "$umount" ] && umount="$(abspath "$umount" "$configdir")"
args=("${args[@]}" "$backup" "$destdir" "$vgname" "$lvname" "$includes" "$excludes" "$script" "$mount" "$umount")
done
# ce script doit tourner en root
if is_root; then
action=backup
set -- "${args[@]}"
else
run_as_root --backup --lockfile "$lockfile" ${halt:+-H }${fake_maybe:+-n }"${args[@]}"
fi
fi
if [ "$action" == "backup" ]; then
no_error=1
function err_result() {
shift # STATUS
eerror "$*"
no_error=
}
while [ -n "$*" ]; do
backup_name="$1"; shift
backup_destdir="$1"; shift
backup_vgname="$1"; shift
backup_lvname="$1"; shift
backup_includes="$1"; shift
backup_excludes="$1"; shift
backup_script="$1"; shift
backup_mount="$1"; shift
backup_umount="$1"; shift
etitle "${backup_name:-DEFAULT}"
result="$("$backup_mount" "$backup_destdir" "$backup_vgname" "$backup_lvname")"
if [ $? -ne 0 ]; then
err_result $result
else
suffix="${backup_name:+-$backup_name}"
last="last$suffix"
destdir="$backup_destdir"
mkdir -p "$destdir"
# calculer les répertoires de destination et ceux à supprimer
eval "$("$scriptdir/plbck" -S "$suffix" -e "$destdir")"
# sauvegarder
etitle -s "Sauvegarde dans $CURRENT${PREVIOUS:+ depuis $PREVIOUS}"
error=
if $fake_maybe rsync -aHAX --delete ${PREVIOUS:+--link-dest="$PREVIOUS"} \
${backup_excludes:+--delete-excluded --exclude-from="$backup_excludes"} \
--include-from="$backup_includes" \
/ "$CURRENT"; then
cwd="$(pwd)"
cd "$destdir"
[ -L "$last" ] && $fake_maybe /bin/rm -f "$last"
$fake_maybe ln -s "$(basename "$CURRENT")" "$last"
cd "$cwd"
[ -n "$backup_commands" ] && $fake_maybe source "$backup_commands"
else
err_result 1 "Une erreur s'est produite pendant la sauvegarde. Arrêt des opération pour $backup_name"
error=1
fi
eend
# supprimer
if [ -z "$error" -a -n "${DELETES[*]}" ]; then
etitle -s "Suppression des anciennes versions"
for delete in "${DELETES[@]}"; do
estep "$delete"
$fake_maybe rm_maybe -rf "$delete"
done
eend
fi
# démonter le répertoire
result="$("$backup_umount" $result)"
if [ $? -ne 0 ]; then
err_result $result
fi
fi
done
rm "$lockfile"
if [ -n "$no_error" -a -n "$halt" ]; then
$fake_maybe /sbin/shutdown -h now
fi
else
die "Action inconnue: $action"
fi