Table des matières
Introduction
Cet article présente un outil de calcul automatique des périodes d'activité (ou “uptime” en anglais) et d'inactivité d'un ordinateur sur une période de temps de longueur quelconque caractérisée par une date initiale donnée.
Le système est dit actif dès qu'il est démarré, on doit donc mémoriser chaque date de démarrage (ou “boot”), et réciproquement l'activité se termine quand on arrête le système.
Le script Python présenté est donc utilisable à 3 niveaux :
- automatiquement au moment du boot pour mémoriser le démarrage de l'activité,
- automatiquement à l'arrêt pour mémoriser la fin de l'activité,
- à la demande par tout utilisateur pour s'informer des valeurs courantes des compteurs.
Exemple de listage obtenu :
Date courante : 09/08/2006 19:15:07 Date du boot courant : 09/08/2006 19:12:33 Date initiale : 07/08/2006 17:13:52 Nombre total de boots : 11 Duree totale : 180076 secondes, soit 2 jours, 2 heures, 1 minute et 16 secondes Duree active courante : 155 secondes, soit 2 minutes et 35 secondes Duree active moyenne : 3087 secondes, soit 51 minutes et 27 secondes Duree active maximale : 4851 secondes, soit 1 heure, 20 minutes et 51 secondes Duree active cumulee : 33955 secondes, soit 9 heures, 25 minutes et 55 secondes, ou 18.86% de la duree totale Duree inactive : 146121 secondes, soit 1 jour, 16 heures, 35 minutes et 21 secondes, ou 81.14% de la duree totale
En fin d'article on présentera aussi un script Bash permettant de créer un service système qui consiste à lancer l'outil automatiquement au boot et à l'arrêt du système.
Article rédigé par Jeanmm
Version initiale : 8/8/2006.
Le script Python
Voici le script, et pour les explications voir les commentaires inclus et le paragraphe qui suit le script. On conseille d'en enregistrer une version exécutable qu'on nommera uptime2, par exemple dans /usr/local/bin (uptime existe déjà dans /usr/bin).
#!/usr/bin/python # -*- coding: iso-8859-1 -*- """ Ce module est un outil de calcul de temps d'activité (uptime) d'un système. En principe on fait en sort de démarrer la phase d'activité au boot, et d'en marque la fin à l'arrêt du système. L'outil s'appuie sur 3 petits fichiers textes, dont les noms exacts sont modifiables dans ce script : - dateBoot : contient la date courante à chaque boot - dateInitiale : contient la date initiale de référence, en principe fixée une fois pour toutes. - uptimeCumule : contient la somme des durées d'activité, en secondes; à chaque arrêt du système on y ajoute la durée de la période d'activité courante qui se termine. Arguments possibles : start : Appel lors du boot stop : Appel lors de l'arrêt du système sinon on liste simplement les compteurs courants. Les appels start et stop peuvent être effectués par root, avec des fichiers protégés en écriture mais lisibles de tous, ce qui fait que l'appel sans paramètres pourra se faire à tout moment sans être root. Version initiale : 08/08/2006 Auteur : Jeanmm Licence : GPL Lien : www.root66.net """ import sys, os, shutil, time, string # Parametres du programme (les 3 noms de fichiers) : # - dateBoot : écrit à chaque boot, sinon créé à la date courante # - dateInitiale : doit exister, sinon copie de dateBoot # - uptimeCumule : doit exister, sinon créé à zéro # Si le dossier du fichier dateBoot n'existe pas on tentera de le créer dateBoot = '/usr/local/uptime2/dateBoot.txt' dateInitiale = '/usr/local/uptime2/dateInitiale.txt' uptimeCumule = '/usr/local/uptime2/uptimeCumule.txt' # Conversion d'une duree de secondes en 'années, mois, jours...' def zDuree(x): if x >= 31536000: (q, r) = divmod(x, 31536000) if q > 1: z = "%.0f" %(q) + " ans, " else: z = "1 an, " x = x - q * 31536000 else: z = "" if x >= 86400: (q, r) = divmod(x, 86400) if q > 1: z = z + "%.0f" %(q) + " jours, " else: z = z + "1 jour, " x = x - q * 86400 if x >= 3600: (q, r) = divmod(x, 3600) if q > 1: z = z + "%.0f" %(q) + " heures, " else: z = z + "1 heure, " x = x - q * 3600 if x >= 60: (q, r) = divmod(x, 60) if q > 1: z = z + "%.0f" %(q) + " minutes et " else: z = z + "1 minute et " x = x - q * 60 if x > 1: z = z + "%.0f" %(x) + " secondes" else: z = z + "%.0f" %(x) + " seconde" return z # Programme principal # ------------------- if __name__=='__main__': # Parametres d'appel N = len(sys.argv) start = 0 # 1 si appel lors du boot stop = 0 # 1 si appel lors de l'arrêt du système if N > 0: for i in range(N): # Appel lors du boot if sys.argv[i] == 'start': start = 1 # Appel lors de l'arrêt du système elif sys.argv[i] == 'stop': stop = 1 # Help elif sys.argv[i] == '-h' or sys.argv[i] == 'help' or sys.argv[i] == '--help': print "Cet outil calcule la duree d'activite (uptime) du systeme" print "Arguments possibles :" print " start : Appel lors du boot," print " stop : Appel lors de l'arret du systeme," print " sinon listage des compteurs courants." print "Auteur : Jeanmm - www.root66.net" print "Licence : GPL" sys.exit(0) # date courante x = time.localtime() # tuple t = time.time() # float # idem sous forme de chaîne xx = time.strftime('%d/%m/%Y %H:%M:%S') # Test si le fichier de boot existe, sinon on tente de le créer if not os.path.isfile(dateBoot): # si le dossier n'existe pas on tente de le créer if not os.path.isdir(os.path.dirname(dateBoot)): try: os.makedirs(os.path.dirname(dateBoot)) except: pass try: fb = open(dateBoot, 'w') fb.write(xx + '\n') fb.close() print "Le fichier '" + dateBoot + "' a ete initialise !" except: print "Erreur : le fichier '" + dateBoot + "' ne peut pas etre ecrit !" sys.exit(1) # Test si le fichier initial existe if not os.path.isfile(dateInitiale): try: shutil.copy(dateBoot, dateInitiale) if not stop: print "Le fichier '" + dateInitiale + "' a ete initialise !" except: print "Erreur : le fichier '" + dateInitiale + "' ne peut pas etre cree," print " et/ou bien le fichier '" + dateBoot + "' n'existe pas !" sys.exit(1) # Cas de l'appel au boot # On écrit la date courante dans dateBoot if start: try: fb = open(dateBoot, 'w') fb.write(xx + '\n') fb.close() except: print "Erreur : le fichier '" + dateBoot + "' ne peut pas etre ecrit !" sys.exit(1) print "Le fichier '" + dateBoot + "' a ete ecrit : %s" %(xx) if not stop: print "Date courante : %02d/%02d/%04d %02d:%02d:%02d" %(x[2], x[1], x[0], x[3], x[4], x[5]) # Lecture du fichier de boot # qui contient une date 'jj/mm/aaaa hh:mm:ss' try: fb = open(dateBoot, 'r') zb = fb.read() fb.close() except: print "Erreur : le fichier '" + dateBoot + "' ne peut pas etre lu !" sys.exit(1) if zb[-1] == '\n': zb = zb[0:-1] tb = time.strptime(zb, '%d/%m/%Y %H:%M:%S') if not stop: print "Date du boot courant : " + zb # Lecture du fichier de cumul # qui contient un nombre flottant en secondes try: fc = open(uptimeCumule, 'r') zc = fc.read() fc.close() except: fc = open(uptimeCumule, 'w') fc.write('0.0 0 0.0\n') fc.close() print "Le fichier '" + uptimeCumule + "' a ete initialise !" zc = '0.0' # Le fichier contient le cumul, ou de plus le nombre de sessions et l'uptime max v = string.split(zc) tc = float(v[0]) if len(v) > 1: ns = int(v[1]) else: ns = 0 if len(v) > 2: um = float(v[2]) else: um = 0.0 # Lecture du fichier initial # qui contient une date 'jj/mm/aaaa hh:mm:ss' try: fi = open(dateInitiale, 'r') zi = fi.read() fi.close() except: print "Erreur : le fichier '" + dateInitiale + "' ne peut pas etre lu !" sys.exit(1) if zi[-1] == '\n': zi = zi[0:-1] ti = time.strptime(zi, '%d/%m/%Y %H:%M:%S') if not stop: print "Date initiale : " + zi # durées totale, cumulée, nombre de sessions (ou boots) et durée max t = time.time() dureeTotale = t - time.mktime(ti) cumulDuree = tc + (t - time.mktime(tb)) ns += 1 if (t - time.mktime(tb)) > um: um = (t - time.mktime(tb)) # listage des valeurs courantes if not stop: print "Nombre total de boots : %i" %(ns) print "Duree totale : %.0f secondes, soit %s" %(dureeTotale, zDuree(dureeTotale)) print "Duree active courante : %.0f secondes, soit %s" %(t - time.mktime(tb), zDuree(t - time.mktime(tb))) m = cumulDuree / ns print "Duree active moyenne : %.0f secondes, soit %s" %(m, zDuree(m)) print "Duree active maximale : %.0f secondes, soit %s" %(um, zDuree(um)) p = 100.0 * cumulDuree / dureeTotale print "Duree active cumulee : %.0f secondes, soit %s, ou %.2f" %(cumulDuree, zDuree(cumulDuree), p) + "% de la duree totale" dif = dureeTotale - cumulDuree p = 100.0 * dif / dureeTotale print "Duree inactive : %.0f secondes, soit %s, ou %.2f" %(dif, zDuree(dif), p) + "% de la duree totale" if stop: # mise-à-jour du fichier de cumul fc = open(uptimeCumule, 'w') fc.write(str(cumulDuree) + ' ' + str(ns) + ' ' + str(um) + '\n') fc.close() sys.exit(0)
Intégration dans le système
Pour intégrer le script au niveau du boot et de l'arrêt du système on peut créer un script Système /etc/init.d/uptime2 contenant :
#!/bin/sh # # chkconfig: 2345 99 09 # description: uptime2 est un outil de mesure des durees d'activite du systeme # # Librairie de fonctions . /etc/rc.d/init.d/functions SYSCONF_FILE=/var/lock/subsys/uptime2 case $1 in start) /usr/bin/python /usr/local/bin/uptime2 start touch $SYSCONF_FILE ;; stop) if [ -f $SYSCONF_FILE ] then /usr/bin/python /usr/local/bin/uptime2 stop rm -f $SYSCONF_FILE else gprintf "uptime2 n'est pas en service\n" exit 1 fi ;; status) if [ -f $SYSCONF_FILE ] then gprintf "uptime2 est en service\n" else gprintf "uptime2 n'est pas en service\n" fi ;; restart) $0 stop sleep 1 $0 start ;; *) gprintf "Usage: %s\n" "$(basename $0) {start|stop|status|restart}" exit 1 ;; esac
On l'installe ensuite par la commande :
chkconfig --add uptime2
Ces manips vont lancer le script à chaque boot aux niveaux d'exécution 2 à 5 (5 est le plus courant pour les utilisateurs), et pour l'arrêt quand le système passe au niveau d'exécution 6. Uptime2 est ainsi vu comme un véritable service système; dans une Mandriva il apparaîtra par exemple dans la liste des services au niveau du CCM.
Remarque : Le dossier du fichier de boot (un des 3 fichiers nécessaires au fonctionnement d'uptime2), ici /usr/local/uptime2, est créé s'il n'existait pas. On a intérêt à déclarer les 3 fichiers de données nécessaires à l'outil dans ce même dossier, qui devra éventuellement être créé manuellement si la tentative de création automatique échouait.
Normalement au 1er reboot du système les 3 fichiers nécessaires à l'outil seront créés, la date initiale étant une fois pour toutes mise à la date de ce reboot. On peut aussi créer les 3 fichiers en lançant uptime2 une première fois en root. On pourra ensuite, de préférence après un reboot, lancer uptime2 en mode root ou utilisateur, sans paramètres, pour vérifier que ça fonctionne; on vérifiera notamment que le compteur de boot s'incrémente de 1 à chaque fois.