#!/bin/bash ## CHECK ## Verifie que les programmes fonctionnent et les relance si ils sont en panne ## Doit etre lance par cron. On peut par exemple mettre un /etc/cron.d/check ## qui contient : ## * * * * * root /usr/sbin/check PATH="/sbin:/bin:/usr/sbin:/usr/bin" ## Configuration dans un fichier exterieur : /etc/check.conf if [ "`whoami`" != "root" ]; then echo "Check lance par un autre utilisateur que root : EXIT" exit fi RUNLEVEL=`runlevel | cut -f 2 -d ' '` if [ $RUNLEVEL -eq 0 ] || [ $RUNLEVEL -eq 6 ]; then echo "Arret ou reboot en cours : on sort" exit fi if [ $RUNLEVEL -eq 1 ]; then echo "Démarrage en cours : on sort" exit fi if [ -f "/tmp/check-bloque" ]; then # Check est bloque par un programme externe : on sort exit fi function checklog() { # Loggue dans /var/log/check.log tous les arguments passes a la fonction # Ne doit pas se retrouver dans le fichier de configuration (sauf pour test # de demarrage de l'application check) echo "`date +"%b %d %T"` `hostname` check - $@" >> /var/log/check.log if [ "$alerteAudio" == "TRUE" ]; then rc=`/usr/bin/alerte.php "$@"` if [ "$rc" != "OK" ]; then echo $rc fi fi if [ "$alerteNotify" == "TRUE" ]; then rc=`/usr/bin/notify-send -u critical -t 2000 "$@"` if [ "$rc" != "OK" ]; then echo $rc fi fi if [ "$alerteAudio" != "TRUE" ] && [ "$alerteNotify" != "TRUE" ]; then # Si aucun moyen de communication n'est demandé, on écrit à l'écran echo "$@" fi } function chercheLanceur() { # Cette fonction renvoie le lanceur du programme passé en paramètre # On peut définir un tableau supplémentaire dans le fichier de configuration # Si le lanceur n'est pas défini dans le tableau, on renvoie le nom du # processus if [ $BASH_VERSINFO -ge 4 ]; then processus=$1 if [ -z ${lanceur["$processus"]} ]; then echo "$processus" else echo ${lanceur["$processus"]} fi else # Le Bash 3 ne supporte pas les tableaux associatifs. On retourne aux liens # symboliques echo $1 fi } function testps() { lanceur=`chercheLanceur "$1"` if [ ! -e "/etc/init.d/$lanceur" ]; then checklog "ERREUR : /etc/init.d/$lanceur introuvable (testps)" else if [ `ps -edf | grep -v grep | grep "$*" | wc -l` -eq 0 ]; then checklog "Relance de '$*' par /etc/init.d/$lanceur" /etc/init.d/$lanceur stop /etc/init.d/$lanceur start fi fi } function testpsStrict() { # On rend le test plus strict en mettant un slash devant le nom du demon lanceur=`chercheLanceur "$1"` if [ ! -e "/etc/init.d/$lanceur" ]; then checklog "ERREUR : /etc/init.d/$lanceur introuvable (testpsStrict) " else if [ `ps -edf | grep -v grep | grep "/$*" | wc -l` -eq 0 ]; then checklog "Relance de '$*' par /etc/init.d/$lanceur" /etc/init.d/$lanceur stop /etc/init.d/$lanceur start fi fi } function testiptables() { # Verifie que iptables est bien ferme if [ ! -e "/etc/init.d/ipt4" ] && [ ! -e "/etc/init.d/ipt" ]; then checklog "ERREUR : /etc/init.d/ipt4 ou /etc/init.d/ipt introuvable (testiptables) " else if [ `/sbin/iptables -L -n | wc -l` -lt 10 ]; then checklog "Relance de IPTables IPv4" if [ -e "/etc/init.d/ipt4" ]; then /etc/init.d/ipt4 start else /etc/init.d/ipt start fi fi fi } function testip6tables() { # Verifie que ip6tables est bien ferme if [ ! -e "/etc/init.d/ipt6" ]; then checklog "ERREUR : /etc/init.d/ipt6 introuvable (testip6tables) " else if [ `/sbin/ip6tables -L -n | wc -l` -lt 10 ]; then checklog "Relance de IPTables IPv6" /etc/init.d/ipt6 start fi fi } function testDNS() { # Verifie si le DNS a change pour l'adresse passe en argument NEW="`host -t A $1 2>/dev/null`" if [ "$?" != "0" ]; then return; fi if [ "$NEW" != "`cat /var/lib/check 2>&1 /dev/null`" ]; then checklog "Changement d'adresse pour $1 : `host -t A $1`" echo "ALERTE : Nouvelle adresse DNS pour $1 :" echo " Ancienne : `cat /var/lib/check 2>&1 /dev/null`" echo " Nouvelle : $NEW" host -t A $1 > /var/lib/check fi } function testdf() { # Teste tous les disques et renvoie si le disque est plein a plus de 84% # On peut aussi tester les disques unitairement : # testdf /mnt # On peut aussi tester unitairement avec une limite differente de 84% # testdf /mnt 90 if [ -z "$2" ]; then limite=84 else limite=$2 fi if [ ! -z "$1" ]; then fs="$1" fi IFS=" " for ligne in `df -P -l -x tmpfs -x devtmpfs $fs | sed '/Used Available/d'`; do fs_space=`echo $ligne | awk '{print $5}'| sed 's/\%//'` filesys=`echo $ligne | awk '{print $6}'` if [ $fs_space -gt $limite ]; then checklog "Systeme de fichier $filesys plein a $fs_space %" fi done } function testPort() { # Verifie si un port est actif # Attend 3 parametres : l'adresse IP a tester, le port a tester et le # fichier /etc/init.d/XX a relancer if [ ! -e "/etc/init.d/$3" ]; then checklog "ERREUR : /etc/init.d/$3 introuvable (testPort)" else RESULTAT=`echo "QUIT" | nc -w1 $1 $2 2>&1` if [ "$?" != "0" ]; then checklog "Relance de $3 car injoignable par reseau" echo "ALERTE : La machine `hostname` ne peut plus se connecter a " echo "$1 port $2 : $RESULTAT" echo "Relance de $3" /etc/init.d/$3 stop /etc/init.d/$3 start fi fi } function testDDClient() { # Verifie si ddclient est toujours actif. Pour cela, le processus doit avoir # une ligne 'ddclient - sleeping for'. Si ce n'est pas le cas (test en cours) # on attend 15 s et on refait le test. Si le test est toujours negatif on # relance. if [ ! -e "/etc/init.d/ddclient" ]; then checklog "ERREUR : /etc/init.d/ddclient introuvable (testDDClient)" else LIGNE1=`ps -edf | grep -v grep | egrep "ddclient "` LIGNE2=`echo $LIGNE1 | egrep 'ddclient - sleeping for|ddclient - (connecting to|reading from) checkip.dyndns.com port 80'` if [ $? -ne 0 ]; then checklog " DDCLIENT ERREUR 1 (LIGNE1=$LIGNE1///LIGNE2=$LIGNE2)" ps -edf >> /var/log/check.log checklog "ddclient non lance ou pas en mode sleep : relance" echo "Relance de ddclient" /etc/init.d/ddclient stop /etc/init.d/ddclient start fi fi } function testMount() { # Verifie si le point de montage passe en argument est bien monte et en RW # Si pas monte, on le monte. Si en RO, on le passe en RW PNT=$1 MNT=`egrep -v "^{none|rootfs|binfmt_misc|gvfs-fuse-daemon} " /proc/mounts | cut -d " " -f 2 | egrep "^$PNT$"` if [ "$MNT" == "" ]; then checklog "Disque $PNT non monte : remonte" mount $PNT fi ST=`egrep -v "^{none|rootfs|binfmt_misc|gvfs-fuse-daemon} " /proc/mounts | cut -d " " -f 2,4| egrep "^$PNT " | cut -d " " -f 2 | cut -d "," -f 1` if [ "$ST" == "ro" ]; then checklog "Disque $PNT en RO : Passage en RW" mount -o remount,rw $PNT fi } function testRepertoireVide() { # Verifie que le repertoire passe en argument est bien vide REP=$1 if [ "`ls -1 $REP`" != "" ]; then checklog "Repertoire $1 non vide" ls -1 $REP fi } function testBatterie() { # Cette fonction teste la batterie de l'ordinateur si elle est dispo et envoie # une erreur si le niveau tombe sous le seuil defini pour la batterie # Recherche du seuil : SEUIL=`grep "design capacity warning:" /proc/acpi/battery/BAT1/info 2>/dev/null | cut -d " " -f 4` # Recherche de la capacite restante : CAPA=`grep "remaining capacity:" /proc/acpi/battery/BAT1/state 2>/dev/null | cut -d " " -f 8` if [ -n $SEUIL ] && [ -n $CAPA ] && [ $CAPA -lt $SEUIL ]; then checklog "Batterie faible ($CAPA/$SEUIL)" fi } function testNTP() { # Cette fonction teste si NTP est bien synchronisé avec un serveur de temps /usr/bin/ntpq -n -c peers | egrep -q '^\*' || checklog "Serveur de temps asynchronisé ou injoignable" } if [ ! -f "/etc/check.conf" ]; then echo "Le fichier /etc/check.conf n'existe pas : EXIT" exit fi # Lanceur est le tableau associatif des lanceurs 'processus'=>'lanceur' dans # /etc/init.d # On peut définir des lanceurs dans la fonction chercheLanceur, ou dans le # fichier de configuration /etc/check.conf. Si on redéfinit un lanceur dans # /etc/check.conf, c'est lui qui est prioritaire par rapport à ceux codés en dur if [ $BASH_VERSINFO -ge 4 ]; then declare -A lanceur lanceur[bind]="bind9" lanceur[dhcpd]="isc-dhcp-server" lanceur[mysqld]="mysql" lanceur[ntpd]="ntp" lanceur[rsyslogd]="rsyslog" lanceur[spamd]="spamassassin" lanceur[sshd]="ssh" fi . /etc/check.conf if [ "$alerteNotify" == "TRUE" ] && [ ! -f "/usr/bin/notify-send" ]; then echo "Check : alerteNotify demande mais /usr/bin/notify-send non disponible" echo " apt-get install libnotify-bin" exit fi if [ "$alerteAudio" == "TRUE" ] && [ ! -f "/usr/bin/alerte.php" ]; then echo "Check : alerte audio demandée mais /usr/bin/alerte.php non disponible" echo " apt-get install cric-alerte" exit fi