#!/bin/bash

# AUTEUR : GnunuX, http://www.gnunux.info/

# LICENCE :
# Ce logiciel est distribué selon la licence CECILL 2
# Voir http://www.cecill.info/licences/Licence_CeCILL_V2-fr.html

export LC_ALL="fr_FR.utf8"		# langue
REPSAUVS="/mnt/racine/sauv/ /mnt/hd/sauv/" # repertoire de sauvegarde
REPS="/etc rsync://util@192.168.1.5/conf
/home/httpd"				# repertoire a sauvegarder
RSYNC_PASSWORD="MotDePassRsync"		# mot de passe rsync
COURRIEL="root"				# courriel de maintenance
EXCLUSION="Musiques"			# repertoire a exclure (voir man rsync)
#MYSQL_MDP="motdepasse"			# mot de passe root de mysql
PAQUET="pacman"				# possible : "", pacman, dpkg, rpm
DEBUG="stat"				# possible : none, stat, debug
LOCK="/tmp/sauv.lock"			# le fichier verrou

export RSYNC_PASSWORD

#-------------------------------------------------------------------------------
# Procedure : sauv_erreur
#-------------------------------------------------------------------------------
# But : s'il y a une erreur grave, envoi un message en console et quitte
# Entree : Le message d'erreur + "non" si on veut garder le fichier $LOCK
# Sortie : Le message en console et quitte le programme
sauv_erreur () {
	mail $COURRIEL -s "La sauvegarde merite votre attention" <<EOF
$1
EOF
	[ ! "$2" = "non" ] && rm $LOCK; 
	exit 1; 
}

#-------------------------------------------------------------------------------
# Procedure : envoi_mail
#-------------------------------------------------------------------------------
# But : procedure d'envoi du courriel d'information
# Entree : le fichier $SAUV_TMP ou $SAUV_TMP_VEILLE avec le contenu du courriel
#          verifie que les repertoires sont tous dans $SAUV2
# Sortie : un courriel descriptif
# Bug : si les fichiers SAUV_TMP et SAUV_TMP_VEILLE n'existent pas
envoi_mail ()
{
	if [ -f $SAUV_TMP ]
	then
		SAUV2=$SAUV_TMP
	else
		SAUV2=$SAUV_TMP_VEILLE
	fi

	MAIL_ERR="";
	for ((i=0; i<${#REP[*]}; ++i))
	do
		if [ ! `grep ${REP[$i]} $SAUV2` ]
		then
			echo "---- ATTENTION : ${REP[$i]} non sauvegarde !\
				----" >> $LOG_MAIL
			MAIL_ERR="NON COMPLETE";
		fi
	done
	>> $LOG_MAIL
	df -h >> $LOG_MAIL
        mail $COURRIEL -s "Sauvegarde du `date` $MAIL_ERR" < $LOG_MAIL
        rm $LOG_MAIL
}

[ -f $LOCK ] && sauv_erreur "La sauvegarde n'est pas fini !" non
touch $LOCK

# niveau d'information retourner dans le courriel
case $DEBUG in
	"none") OPTION_RSYNC="" ;;
	"stat") OPTION_RSYNC="--stats" ;;
	"debug")        OPTION_RSYNC="--stats -v";;
	*)      sauv_erreur "Option DEBUG inconnu"
esac

# verifie les parametres de configuration minimum
[ ! "$REPSAUVS" ] && sauv_erreur "Il me faut au moins un \$REPSAUVS !!"
[ ! "$REPS" ] && sauv_erreur "Il me faut au moins un \$REPS !!"

# fichier comprenant les exclusions
EXCLURE_TMP="/tmp/exlure.tmp"
> $EXCLURE_TMP
EXCLURE_TMP2="/tmp/exlure2.tmp"
echo $EXCLUSION > $EXCLURE_TMP2

# repertoire de sauvegarde
REPSAUV=($REPSAUVS)

# verifie si $REPSAUV[0] n'est pas un repertoire distant
[ "`echo "$REPSAUV[0]" | grep "^/"`" ] || sauv_erreur "Le premier REPSAUV ne\
	doit pas etre distant !!"

REPSAUV_MAITRE="${REPSAUV[0]}/maitre"
REPSAUV_ACTUEL="${REPSAUV[0]}/`date +%A`"
SAUV="non"
SAUV_MAIL="non"
SAUV_TOUT="oui"

# fichier de log temporaire
LOG_TMP="/tmp/sauv.log"
> $LOG_TMP
LOG_MAIL="${REPSAUV[0]}/sauv_mail.log"

# le fichier SAUV_TMP contient les repertoires deja sauvegardes
# le fichier SAUV_TMP_VEILLE est celui de la veille
SAUV_TMP="${REPSAUV[0]}/sauv_`date +%F`.tmp"
SAUV_TMP_VEILLE="${REPSAUV[0]}/sauv_`date --date '1 days ago' +%F`.tmp"

# recupere l'ensemble des repertoires a sauvegarder
cd /
REP=($REPS)

# si le fichier $SAUV_TMP n'existe pas, il faut initialiser la sauvegarde
if [ ! -f $SAUV_TMP ]
then
	# envoi l'eventuel courriel de la veille
	[ -f $LOG_MAIL ] && envoi_mail
	# efface les vieux journaux
	rm -rf ${REPSAUV[0]}/sauv_*.tmp
	# efface la sauvegarde de la semaine derniere et recreer le repertoire
	rm -rf $REPSAUV_ACTUEL
	mkdir -p $REPSAUV_ACTUEL
	# demarre la sauvegarde
	if [ $MYSQL_MDP ]
	then
		echo -e "\n---- Sauvegarde de mysql le `date` ----" >> $LOG_MAIL
		mysqldump --all-databases -uroot -p${MYSQL_MDP} \
			> $REPSAUV_ACTUEL/dumpSQL.sql 2>> $LOG_MAIL
		echo "---- Fini le `date` ----" >> $LOG_MAIL
	fi
	if [ $PAQUET ]
	then
		echo -e "\n---- Sauvegarde de la liste de paquet le `date` \
			----" >> $LOG_MAIL
		case $PAQUET in
			pacman)	pacman -Qe > $REPSAUV_ACTUEL/dumpPACMAN.txt ;;
			dpkg) dpkg --get-selections > \
				$REPSAUV_ACTUEL/dumpDPKG.txt ;;
			rpm) rpm -qa > $REPSAUV_ACTUEL/dumpRPM.txt ;;
			*) sauv_erreur "Systeme de paquet inconnu"
		esac
		echo "---- Fini le `date` ----" >> $LOG_MAIL
	fi
	> $SAUV_TMP
fi

for ((i=0; i<${#REP[*]}; ++i))
do
	SRC=${REP[$i]}

# s'il n'y a pas eu de sauvegarde sur le repertoire, il est sauvegarde
	> $LOG_TMP
# Bug : le repertoire local est du nom du repertoire/partage. Il remplace les /
# par des _. Si par exemple vous sauvegardez /toto/tata/titi et /toto/tata_titi
# ils s'ecraseront (du moins la sauvegarde) mutuellement.
	DST=`echo $SRC | sed "s@/@_@g"`
	if [ ! `grep $SRC $SAUV_TMP` ]
	then
		echo "---- Sauvegarde de $SRC le `date` ----" >> $LOG_TMP
		mkdir -p $REPSAUV_ACTUEL/$DST $REPSAUV_MAITRE/$DST
		rsync --exclude=".Trash" --exclude-from=$EXCLURE_TMP2 --force \
			--ignore-errors --delete --delete-excluded --backup  \
			--backup-dir=$REPSAUV_ACTUEL/$DST -a $SRC            \
			$OPTION_RSYNC $REPSAUV_MAITRE/$DST >> $LOG_TMP 2>&1

# s'il n'y a pas eu d'erreur, il est marque comme sauvegarde
		if [ $? = "0" ]
		then
			 echo "---- Fini le `date` ----" >> $LOG_TMP
			SAUV_MAIL="oui"
			[ "`echo "$SRC" | grep "^/"`" ] && SAUV="oui"
			echo "$SRC" >> $SAUV_TMP
			cat $LOG_TMP >> $LOG_MAIL
		else
			SAUV_TOUT="non"
		fi
	fi

# s'il est sauvegarde, recherche si c'est un repertoire distant pour ne pas
# le copier sur le disque secondaire
	if [ ! "`echo "$SRC" | grep "^/"`" ]
	then
		for rep in maitre lundi mardi mercredi \
			jeudi vendredi samedi dimanche
		do
			echo "$rep/$DST" >> $EXCLURE_TMP
		done
	fi
done

# s'il y a eu sauvegarde, copie sur le ou les disques secondaires
[ "$SAUV" = "oui" ] && [ ${REPSAUV[1]} ] && for ((i=1; i<${#REPSAUV[*]}; ++i))
do
	echo "---- Copie dans ${REPSAUV[$i]} le `date` ----" >> $LOG_MAIL
	rsync --force --ignore-errors --delete --delete-excluded $OPTION_RSYNC \
	 	 --exclude-from=$EXCLURE_TMP -a ${REPSAUV[0]} ${REPSAUV[$i]}   \
		 >> $LOG_MAIL 2>&1
	echo "---- Fini le `date` ----" >> $LOG_MAIL
done

# envoi du courriel
[ "$SAUV_MAIL" = "oui" ] && [ "$SAUV_TOUT" = "oui" ] && envoi_mail

# supprime le fichier temporaire d'exclusion et le verrou
rm $EXCLURE_TMP $LOCK

