403 lines
8 KiB
Bash
Executable file
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 " -s 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
|