backuppcExportOnUsbDisk/backup-usb

403 lines
8 KiB
Bash
Executable file

#!/bin/bash
# Path to backuppcfs script
BACKUPPCFS_PATH="/usr/local/sbin/backuppcfs"
BACKUPPCFS_MNT="/mnt/backuppcfs"
MNT_DIR=/mnt/usb
LUKS_DM_NAME=bkp-usb
LUKS_DM_PATH=/dev/mapper/$LUKS_DM_NAME
LUKS_KEY_FILE="/root/.luks.key"
# LOCK_FILE
LOCK_FILE=/var/lock/bkp-disk.lock
MAIL_FROM=root@localhost
MAIL_TO=root@localhost
function usage() {
echo "Usage : backup-usb [-d] [-s|-c|-f|-o] [-l /path/to/log.file] [-u /dev/sdX]"
echo " -d Debug mode"
echo " -d Status mode : print status mode"
echo " -c Clean status mode : try to :"
echo " - umount device and BackupPC-FS"
echo " - close LUKS device"
echo " - remove lock file"
echo " -f FSCK mode : Run FSCK on device"
echo " -o Open mode : lock, open and mount device"
echo " -l Log file path"
echo " -u Path of USB disk device"
}
DEBUG=0
SEND_MAIL=1
STATUS_MODE=0
CLEAN_MODE=0
FSCK_MODE=0
OPEN_MODE=0
LOG=""
DEVICE=""
while getopts ":dscfol:u:h" opt
do
case "$opt" in
d)
DEBUG=1
;;
s)
STATUS_MODE=1
SEND_MAIL=0
;;
c)
CLEAN_MODE=1
SEND_MAIL=0
;;
f)
FSCK_MODE=1
SEND_MAIL=0
;;
o)
OPEN_MODE=1
SEND_MAIL=0
;;
l)
LOG="$OPTARG"
;;
u)
DEVICE="$OPTARG"
;;
h)
usage
exit 0
;;
*)
echo "Invalid '$opt' parameter"
echo
usage
exit 1
esac
done
#
# Functions
#
function is_mount () {
mount | grep -c "$1 "
}
function send_mail () {
[ $SEND_MAIL -eq 0 ] && return
echo -e "$2"|mail -s "$1" -r "$MAIL_FROM" "$MAIL_TO"
}
REPORT=""
function debug () {
d=`date "+%Y-%m-%d - %Hh%Mm%Ss"`
if [ -z "$LOG" ]
then
echo -e "$d -- [$1] $2"
else
echo -e "$d -- [$1] $2" >> $LOG 2>&1
fi
REPORT="${REPORT}$d -- [$1] $2\n"
if [ "$1" == "HALT" ]
then
beep -f 300 -l 2000
fi
if [ "$3" == "send" -a $SEND_MAIL -ne 0 ]
then
if [ -z "$LOG" ]
then
echo "$d -- [INFO] Send mail"
else
echo "$d -- [INFO] Send mail" >> $LOG 2>&1
fi
send_mail "[$1] Export sauvegardes Backup PC" "$2"
fi
}
function send_report () {
[ $DEBUG -eq 1 -o $SEND_MAIL -eq 0 ] && return 0
[ -n "$REPORT_DF_START" ] && REPORT="${REPORT}\n\n${REPORT_DF_START}"
[ -n "$REPORT_DF_END" ] && REPORT="${REPORT}\n\n${REPORT_DF_END}"
if [ "$1" == "error" ]
then
send_mail "[ERREUR] Export sauvegardes Backup PC : fin de l'export" "/\!\\ Intervention manuelle requise avant de débrancher le disque /\!\\\n\n$REPORT"
else
send_mail "[INFO] Export sauvegardes Backup PC : fin de l'export" "$REPORT"
fi
}
function disk_info() {
VENDOR=$( lsblk -o VENDOR $DEVICE|tail -n1 )
SIZE=$( lsblk -o SIZE $DEVICE|tail -n1 )
UUID=$( lsblk -o UUID $DEVICE|tail -n1 )
echo "$VENDOR $SIZE / UUID : $UUID"|sed 's/ \+/ /g'
}
function checkAndLock() {
if [ -f $LOCK_FILE ]
then
debug ERREUR "Le fichier de lock est toujours présent ($LOCK_FILE)." send
debug HALT
exit 1
fi
debug INFO "Dépot du fichier de lock."
echo $$ > $LOCK_FILE
}
function unlock() {
debug INFO "Suppression du fichier de lock"
rm -f $LOCK_FILE
}
function openDevice() {
if [ -e $LUKS_DM_PATH ]
then
debug ERREUR "Le device $LUKS_DM_NAME existe deja ($LUKS_DM_PATH)." send
debug HALT
exit 1
fi
debug INFO "Ouverture du disque LUKS ..."
cryptsetup luksOpen $DEVICE $LUKS_DM_NAME --key-file $LUKS_KEY_FILE
RES=$?
if [ $RES -ne 0 ]
then
debug ERREUR "La commande 'cryptsetup luksOpen' n'a pas retourne 0. Code retour : $RES" send
debug HALT
exit $RES
else
debug INFO "Fait."
fi
}
function mountDevice() {
if [ `is_mount $LUKS_DM_PATH` -eq 1 ]
then
debug ERREUR "Le disque est déjà monté" send
debug HALT
exit 1
fi
debug INFO "Montage du disque."
mount $LUKS_DM_PATH $MNT_DIR
if [ `is_mount $LUKS_DM_PATH` -eq 0 ]
then
debug ERREUR "Problème durant le montage du disque dur." send
debug HALT
exit 1
fi
}
function closeDevice() {
debug INFO "Fermeture du disque LUKS..."
cryptsetup close $LUKS_DM_NAME
RES=$?
if [ $RES -ne 0 ]
then
debug ERREUR "Problème durant la fermeture du disque LUKS" send
debug HALT
send_report error
exit 1
fi
}
function statusMode () {
if [ -f $LOCK_FILE ]
then
debug INFO "Fichier de lock present"
if [ $( ps xa|grep rsync|grep -c "$BACKUPPCFS_MNT" ) -gt 0 ]
then
debug INFO "Un export de sauvegarde est en cours (commande rsync détectée)"
else
debug ERREUR "Aucun export de sauvegarde détecté (pas de commande rsync détectée).\n\nSi le problème predure depuis plusieurs limite, lancer la commande '$0 -c'"
fi
else
debug INFO "Fichier de lock absent"
fi
if [ -e $LUKS_DM_PATH ]
then
debug INFO "Disque LUKS ouvert"
if [ `is_mount $LUKS_DM_PATH` -eq 1 ]
then
debug INFO "Disque LUKS monté"
df -h $LUKS_DM_PATH
else
debug INFO "Disque LUKS non-monté"
fi
else
debug INFO "Disque LUKS non-ouvert"
fi
if [ `is_mount $BACKUPPCFS_MNT` -eq 1 ]
then
debug INFO "BackupPC-FS monté"
else
debug INFO "BackupPC-FS non-monté"
fi
}
function cleanMode () {
umount $MNT_DIR
cryptsetup close $LUKS_DM_NAME
umount $BACKUPPCFS_MNT
rm -f $LOCK_FILE
}
function fsckMode() {
debug INFO "Début du test FSCK du disque USB $DEVICE ($( disk_info ))"
checkAndLock
beep -f 1000 -r 2 -l 100
openDevice
fsck $LUKS_DM_PATH
RET=$?
if [ $RET -eq 0 ]
then
closeDevice
unlock
fi
exit $RET
}
function openMode() {
debug INFO "Ouverture et montage du disque USB $DEVICE ($( disk_info ))"
checkAndLock
beep -f 1000 -r 2 -l 100
openDevice
mountDevice
exit 0
}
function exportBackupMode() {
debug INFO "Début de l'export des sauvegardes Backup PC sur le disque USB $DEVICE ($( disk_info ))" send
checkAndLock
beep -f 1000 -r 2 -l 100
openDevice
mountDevice
debug INFO "Disque monté. Espace sur le disque USB avant l'export :\n\n$( df -hP $MNT_DIR )\n"
debug INFO "Montage de BackupPC FS..."
$BACKUPPCFS_PATH $BACKUPPCFS_MNT
RES=$?
if [ $RES -ne 0 ]
then
debug ERREUR "Problème durant le montage de BackupPC FS. Code retour : $RES"
umount $BACKUPPCFS_MNT
umount $LUKS_DM_PATH
cryptsetup close $LUKS_DM_NAME
debug HALT
exit 1
else
debug INFO "Fait."
fi
sleep 2
debug INFO "Export des sauvegardes ..."
for dir in $BACKUPPCFS_MNT/*
do
[ ! -d "$dir" -o ! -L "$dir/latest" ] && continue
host="$( basename "$dir")"
latest=$( readlink -e "$dir/latest" )
[ ! -d "$latest" ] && debug ERREUR "Problème durant la résolution du lien de la dernière sauvegarde du serveur $host" && continue
debug INFO "Export de la dernière sauvegarde du serveur $host (sauvegarde n° $( basename $latest )) ..."
rsync -a --delete --numeric-ids --exclude='/dev/*' --exclude='/lib/udev/devices/*' --exclude='PaxHeader' --exclude='WinSxS/*' "$latest/" "$MNT_DIR/$host/"
RES=$?
if [ $RES -ne 0 -a $RES -ne 24 ]
then
debug ERREUR "Problème durant l'export de la sauvegarde du serveur $host (Code retour : $RES)" send
else
debug INFO "Fait."
fi
done
debug INFO "Export des sauvegardes terminé. Espace sur le disque USB après l'export :\n\n$( df --sync -hP $MNT_DIR )\n"
debug INFO "Démontage de BackupPC FS..."
umount $BACKUPPCFS_MNT
RES=$?
if [ $RES -ne 0 ]
then
debug ERREUR "Problème durant le démontage de BackupPC FS (Code retour : $RES)" send
else
debug INFO "Fait."
fi
debug INFO "Démontage du disque"
umount $LUKS_DM_PATH
if [ `is_mount $LUKS_DM_PATH` -eq 1 ]
then
debug ERREUR "Problème durant le démontage du disque dur." send
debug HALT
send_report error
exit 1
else
debug INFO "Fait."
fi
closeDevice
unlock
debug INFO "Fin de l'export."
send_report
beep -f 1000 -l 2000
}
# Manage status/clean mode
if [ "$STATUS_MODE" == "1" ]
then
statusMode
exit 0
elif [ "$CLEAN_MODE" == "1" ]
then
cleanMode
exit 0
fi
if [ -z "$DEVICE" ]
then
debug FATAL "Il faut specifié le disque USB avec le paramètre -u !"
usage
exit 1
elif [ "$FSCK_MODE" == "1" ]
then
fsckMode
exit $?
elif [ "$OPEN_MODE" == "1" ]
then
openMode
exit $?
else
# Else : we are in backup mode
if [ -n "$LOG" ]
then
# Close STDOUT file descriptor
exec 1<&-
# Close STDERR FD
exec 2<&-
# Open STDOUT as $LOG file for read and write.
exec 1<>$LOG
# Redirect STDERR to STDOUT
exec 2>&1
fi
exportBackupMode
fi