« Le système d'exploitation GNU-Linux/Scripts de surveillance » : différence entre les versions
Contenu supprimé Contenu ajouté
m Bot : Ajout de la catégorie Catégorie:Le système d'exploitation GNU-Linux (livre) |
m Modèle:Linux using AWB |
||
Ligne 1 : | Ligne 1 : | ||
{{Linux}} |
|||
Ce chapitre contient différents scripts de surveillance de l'activité d'un serveur Linux |
Ce chapitre contient différents scripts de surveillance de l'activité d'un serveur Linux |
||
Version du 24 mai 2011 à 08:46
Ce chapitre contient différents scripts de surveillance de l'activité d'un serveur Linux
En langage Python
alimon.py (A LInux MONitor)
Lien direct : alimon.py.
#!/usr/bin/python # -*- coding: utf-8 -*- # ############################################################################## # # ALiMon.py : A LInux MONitor # ############################################################################## # # Ce script réalise différentes opérations de monitoring et met en évidence # certains points importants comme une partition disque bientôt pleine ou une # charge processeur trop élevée. # # Ce script a été réalisé durant une scéance de travaux pratiques et a des fins # didactiques. Il est issu du travail collectif des personnes citées ci-dessous # en auteurs et a nécessité uniquement deux heures de développement. # ############################################################################## # # Auteurs : # # David BISPO, Christophe CARLIER, Jonathan DUHAIL, Jonathan GAULUPEAU, # Lahoucine HAMOUCHE, Hicham OUHNA, Manuel PIRES, Yann VAITILINGOM, # Jérémy PELLAUMAIL et Alexandre GUY # # Nous remercions également les connectés du canal #afpy du réseau Freenode # pour leur aide concernant l'unicode et l'encodage utf-8. # # Version : 0.3 # ############################################################################## # # Ce script est diffusé sous la licence EUPL v1.1 # # This script is released under EUPL v1.1 # # http://ec.europa.eu/idabc/eupl # ############################################################################## # # Ce programme est un logiciel libre ; vous pouvez le re-distribuer et/ou le # modifier au titre des clauses de la European Union Public Licence (EUPL) # version 1.1, telle que publiée par l'Union Européenne. # # Ce programme est distribué dans l'espoir qu'il sera utile, # mais SANS AUCUNE GARANTIE ; sans même une garantie implicite de # COMMERCIABILITÉ ou DE CONFORMITÉ À UNE UTILISATION PARTICULIÈRE. # Voir la EUPL version 1.1 pour plus de détails. # # This program is free software; you can redistribute it and/or modify it # under the terms of the European Union Public Licence (EUPL) version 1.1 # as published by the European Union. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the EUPL version 1.1 for more details. # ############################################################################## # # Utilisation manuelle : ./alimon.py # # Utilisation automatisée : Rajouter dans le cron : # 55 23 * * * root alimon.py # ############################################################################## ######################################### #### Configuration & pré-traitements #### ######################################### #### Modules importés #### import commands, unicodedata, os, sys, getopt #### Fonction Affichage du titre formaté #### def titre(message): message = unicode(message,'utf-8') print "\n", "#" * 59 print "######", message.center(45).encode('utf-8'), "######" print "#" * 59, "\n" #### Fonction affichant l'aide #### def usage(): print "###### Aide de alimon ######" print "./alimon.py [-f] [-d] [-h]" print " -f Lance le programme en mode dégradé. Utile si certaines commandes" print " ne sont pas installées sur le serveur." print " -d Lance le programme en mode debug." print " -h Affiche l'aide du programme." #### Variables globables #### # Active / désactive le mode debug debug = 0 # Active / désactive le mode dégradé force = 0 # Seuil maxi du loadavg seuil_maxi_loadavg = 1.0 # Température maxi des disques durs temperature_hdd_maxi = 45 # Taux d'occupation maxi des disques durs taux_occupation_maxi = 80 # Logins autorisés loginsok = ['alex', 'jo'] # Liste des daemons qui doivent être en cours d'exécution proclist = ['sshd', 'apache2', 'mysqld', 'named', 'master', 'murmurd', 'pop3-login', 'teamspeak-serve', 'couriertcpd'] # Pourcentage maxi de swap pourcentage_mem_maxi = 10 # Mémoire mini disponible en Mo mem_mini = 200 # Liste des sites à 'pinguer' url_ping = ['www.google.fr'] # Liste des périphériques RAID (exemple : ['md0', 'md1']) raidlist = [] #### Récupère les arguments #### # Récupère la liste des arguments try: optlist, list = getopt.getopt(sys.argv[1:], 'dhf') # Si un argument ne figure pas dans la liste prédéfinie, affiche la fonction 'usage' (aide) puis quitte except getopt.GetoptError: usage() sys.exit(1) # Traite les arguments donnés for opt in optlist: if opt[0] == '-h': usage() sys.exit(0) if opt[0] == '-d': debug = 1 if opt[0] == '-f': force = 1 #### Test de présence des commandes shell et récupération de leur chemin #### commandes_utilisees = ['cat','hostname','last','hddtemp','df','ps','free','ping','grep','uniq','who','uname'] # Contrôle la commande 'mdadm' uniquement si une liste de disques raid est définie if raidlist: commandes_utilisees.append('mdadm') commandes = {} for comm in commandes_utilisees: (res,commande) = commands.getstatusoutput("/usr/bin/which %s" % comm) # Si une commande n'existe pas mais que le mode Force est activé if res and force: print "La commande", comm, "n'est pas présente sur votre système, fonctionnement en mode dégradé." commandes[comm] = "" # Si une commande n'exite pas elif res: print "La commande", comm, "n'est pas présente sur votre système. Arrêt du programme." print "Tapez './alimon.py -h' pour en savoir plus." sys.exit(1) else: commandes[comm] = commande #### Récupération de la liste des disques durs #### result = commands.getoutput("%s /proc/partitions" % commandes['cat']).split("\n") result.pop(0) hddlist = [] for ligne in result: if debug: print "debug> Ligne du fichier '/proc/partitions' en cours de traitement :", ligne hdd = ''.join(ligne.split()[-1:])[:3] if debug: print "debug> Disque dur à ajouter à la liste :", hdd if hdd and hdd not in hddlist: hddlist.append(hdd) ############################# #### Programme principal #### ############################# #### INFOS SERVEUR #### if commandes['hostname'] and commandes['uname'] and commandes['cat'] and commandes['grep'] and commandes['uniq']: titre("Informations sur le serveur") # On récupère la première ligne du fichier /etc/issue qui contient généralement le nom et la version de la distribution Linux version = open("/etc/issue", "r").readlines()[0][:-1] if debug: print "debug> Version de la distribution :", version # On récupère le nom du serveur hostname = commands.getoutput(commandes['hostname']) if debug: print "debug> Hostname :", hostname print "Serveur %s sous %s" % (hostname, version) print # On récupère et affiche la version du noyau par la commande 'uname -r' print "Noyau Linux :", commands.getoutput("%s -r" % commandes['uname']) # On récupère et affiche le(s) processeur(s) installé(s) sur le serveur cpu = commands.getoutput("%s /proc/cpuinfo | %s \"model name\" | %s" % (commandes['cat'], commandes['grep'], commandes['uniq'])) if debug: print "debug> Liste des processeurs non post-traitée :", cpu print "Processeur(s) :", cpu.split(': ')[1] # On récupère et affiche la quantité de mémoire installée sur le serveur mem = commands.getoutput("%s /proc/meminfo | %s \"MemTotal\"" % (commandes['cat'], commandes['grep'])) if debug: print "debug> Quantité de mémoire non post-traitée :", mem print "Mémoire vive :", ' '.join(mem.split()[1:]) #### DUREE DE FONCTIONNEMENT DU SERVEUR #### if commandes['cat']: titre("Durée de fonctionnement") # On récupère la durée de fonctionnement en secondes dans /proc/uptime result = commands.getoutput("%s /proc/uptime" % (commandes['cat'])).split()[0] duree = float(result) if debug: print "debug> Résultat de cat '/proc/uptime' :", duree # On calcule le reste en secondes secondes = duree%60 if debug: print "debug> Secondes :", secondes # On calcule le reste en minutes minutes = duree/60%60 if debug: print "debug> Minutes :", minutes # On calcule le reste en heures heures = duree/60/60%24 if debug: print "debug> Heures :", heures # On calcule le nombre de jours jours = int(duree/60/60/24) if debug: print "debug> Jours :", jours print "Serveur lancé depuis %i jour(s), %i heure(s), %i minute(s) et %i seconde(s)." % (jours, heures, minutes, secondes) #### VERIFICATION DU LOAD AVERAGE #### if commandes['cat']: titre("Vérification du load average") # On appelle une commande Unix et on récupère le résultat dans la variable result result = commands.getoutput("%s /proc/loadavg" % (commandes['cat'])) if debug: print "debug> Résultat de 'cat /proc/loadavg' :", result # On découpe la chaine de caractères en une liste selon le caractère espace liste_result = result.split() if debug: print "debug> La liste découpée :", liste_result if debug: print "debug> La première valeur de la liste :", liste_result[0] # On compare le load avg de la dernière minute avec le seuil maxi # Attention, on converti la chaine de caractère liste_result[0] en nombre flottant via float() if float(liste_result[0]) > seuil_maxi_loadavg: print "Alerte ! charge CPU supérieure à", seuil_maxi_loadavg, "!!!" else: print "Charge CPU %s normale car inférieure à %.2f" % (liste_result[0],seuil_maxi_loadavg) #### CONNECTIONS DU JOUR #### if commandes['last'] and commandes['grep']: titre("Connections du jour") # On récupère les dernières connections avec la commande 'last', on filtre avec 'grep' login = commands.getoutput("%s | %s \"$(LANG=C date +\"%%a %%b %%-d\")\"" % (commandes['last'], commandes['grep'])) if login == "": login = commands.getoutput("%s | %s \"$(LANG=C date +\"%%a %%b %%-d\")\"" % (commandes['last'], commandes['grep'])) print login #### TEMPERATURE DES HDD #### if commandes['hddtemp']: titre("Températures des disques durs") # On vérifie la température pour chaque disque dans la liste 'hddlist' avec la commande 'hddtemp' for disque in hddlist: if debug: print "debug> Disque en cours de contrôle :", disque # On récupère la température du disque temperature = commands.getoutput("%s -n /dev/%s" % (commandes['hddtemp'], disque)) if debug: print "debug> Température du disque en cours :", temperature # On vérifie que la température du disque n'est pas supérieure au seuil de tolérance, sinon on imprime un message d'alerte # S'il y a une erreur (disque non compatible SMART), on passe au disque suivant try: if int(temperature) > temperature_hdd_maxi: print "Alerte ! Le disque dur /dev/%s a dépassé %s°C, il est actuellement à %s°C !!!" % \ (disque, temperature_hdd_maxi, temperature) else: print "Le disque dur /dev/%s est à %s°C et inférieur au seuil de %s°C" % \ (disque, temperature, temperature_hdd_maxi) except: pass #### VERIFICATION DE L'ESPACE DISQUE #### if commandes['df'] and commandes['grep']: titre("Vérification de l'espace disque") # On récupère le pourcentage d'espace libre sur toutes les partitions dont le périphérique commence par '/dev' avec la commande 'df' result = commands.getoutput("%s -P | %s -e '^/dev'" %(commandes['df'], commandes['grep'])) if debug: print "debug> Résultat du 'df' :", result # On fait un contrôle sur chaque ligne du résultat du 'df' for disque in result.split('\n'): taux_occupation = disque.split()[4][:-1] if debug: print "debug> Disque en cours de contrôle :", disque if debug: print "debug> Taux d'occupation du disque en cours :", taux_occupation # On vérifie que le taux d'occupation n'est pas supérieur au seuil de tolérance, sinon on imprime un message d'alerte if int(taux_occupation) > taux_occupation_maxi: print "Attention la partition %s est rempli à %s !!!" %(disque.split()[0], disque.split()[4]) else: print "La partition %s est pleine à %s." %(disque.split()[0], disque.split()[4]) #### VERIFICATION ETAT RAID #### # Se lance si une liste de périphériques a été définie if raidlist: if commandes['mdadm']: titre("Vérification de l'état du RAID") # On teste chaque périphérique de la liste for hddraid in raidlist: # On récupère le status de la commande qui vérifie l'état d'un RAID (raidstatus, raid) = commands.getstatusoutput("%s --detail -t /dev/%s" %(commandes['mdadm'], hddraid)) # On teste si le status est différent de 0 (donc status en erreur) if raidstatus!=0: print "Attention, le périphérique RAID /dev/%s a au moins un disque en dysfonctionnement !" % hddraid else: print "Le périphérique RAID /dev/%s fonctionne normalement." % hddraid #### VERIFICATION CONNECTIONS EN COURS #### if commandes['who']: titre("Vérification des logins actuellement connectés") # On récupère les noms des utilisateurs actuellement connectés avec la commande 'who' wholiste = commands.getoutput(commandes['who']).split('\n') if debug: print "debug> Liste des utilisateurs connectés :", wholiste liste_logins_connectes = [] # On récupère uniquement la première colonne de chaque ligne for ligne in wholiste: if ligne: if debug: print "debug> Ligne en cours de traitement :", ligne user = ligne.split()[0] if debug: print "debug> Utilisateur en cours de traitement :", user # On ajoute l'utilisateur à une liste s'il n'y est pas déjà (évite les doublons) if user not in liste_logins_connectes: liste_logins_connectes.append(user) # On vérifie que les utilisateurs précédemment récupérés sont bien dans la liste des utilisateurs autorisés, sinon on imprime un message d'alerte for user in liste_logins_connectes: if user in loginsok: print "utilisateur", user, "OK" else: print "ATTENTION L'utilisateur", user, "est connecte MAIS n'est pas dans la liste" #### VERIFICATION DES PROCESSUS #### if commandes['ps']: titre("Vérification des processus") # On récupère les processus lancés avec la commande 'ps' result = commands.getoutput("%s -e" % (commandes['ps'])).split('\n') # On supprime la première ligne result.pop(0) if debug: print "debug> Résultat de la commande 'ps' :", result # On récupère uniquement le nom de chaque processus (dernière colonne) psliste=[] for processus in result: if debug: print "debug> Processus à ajouter :", processus psliste.append(processus.split()[-1]) if debug: print "debug> Contenu de la liste des processus :", psliste # On vérifie que chaque processus de la liste définie au début du script est présent dans la liste récupérée précedemment for processus in proclist: if debug: print "debug> Processus en cours de vérification :", processus if not processus in psliste: print "Attention : le process %s n'est pas lancé actuellement !!!" %(processus) else: print "Le processus", processus, "est bien en cours d'exécution." #### VERIFICATION DE LA MEMOIRE #### if commandes['free']: titre("Vérification de la mémoire") # On récupère la quantité de mémoire libre avec la commande 'free' result = commands.getoutput(commandes['free']) if debug: print "debug> Résultat de la commande 'free' :", result listefree = result.split("\n") if debug: print "debug> On truque le résultat de la commande free pour tester" listefree = [' total used free shared buffers cached', 'Mem: 2066032 850780 1215252 0 114496 368584', '-/+ buffers/cache: 367700 1698332', 'Swap: 2048276 350500 2048276'] print "debug> Free truqué :", listefree # On récupère la quantité de mémoire totale ligne1=listefree[1].split() memoire=float(ligne1[1]) if debug: print "debug> Mémoire totale :", memoire # On récupère la quantité de swap totale ligne3=listefree[3].split() swap=float(ligne3[2]) if debug: print "debug> Swap total :", swap # On calcule le rapport de swap par rapport à la mémoire installée pourcentage = (swap/memoire)*100.0 if debug: print "debug> Pourcentage de Swap :", pourcentage # On vérifie que le rapport ne dépasse pas le seuil limite autorisé, sinon on imprime un message d'alerte if pourcentage > pourcentage_mem_maxi: print "Alerte ! memoire swap supérieur a %d%% de la mémoire (utilisation %.2f%%) !!!" % (pourcentage_mem_maxi, pourcentage) else: print "Mémoire swap inférieure à %d%% (utilisation %.2f%%)" % (pourcentage_mem_maxi, pourcentage) # On récupère la quantité de mémoire libre en Mo avec la commande 'free -m' result = commands.getoutput("%s -m" % (commandes['free'])) result = result.split('\n') if debug: print "debug> Résultat de la commande 'free -m' :", result mem = result[2].split()[3] if debug: print "debug> Quantité de mémoire libre en Mo :", mem # On vérifie que la quantité de mémoire libre ne soit pas inférieure au seuil limite, sinon on imprime un message d'alerte if int(mem) < mem_mini: print "Attention !! il reste moins de %sMo de mémoire libre !!! (%sMo)" %(mem_mini, mem) else: print "Il y a", mem, "Mo de mémoire libre." #### TEMPS DE REPONSE SERVEUR WEB #### if commandes['ping']: titre("Temps de réponse du serveur") # On lance la commande 'ping' sur chaque url définie dans 'url_ping' for url in url_ping: print "Résultat de la commande ping sur %s" % (url) print commands.getoutput("%s -c 1 %s" % (commandes['ping'], url)).split("\n")[-1] print