#!/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