Avis sur un script d'analyse de logs

Avis sur un script d'analyse de logs - Codes et scripts - Linux et OS Alternatifs

Marsh Posté le 03-06-2015 à 10:58:12    

Bonjour,
 
Je cherche 2 ou 3 testeurs pour un petit script d'analyse de logs (en python).
Ca marche chez moi, mais je souhaiterais une vérification par un tiers avant de développer plus le concept. Le mieux serait de tester /var/log/message ou /var/log/auth.log, et tout autre type de logs.
 
Le script est concu pour aider à l'analyse de logs de tout types, et se veut générique. Il regroupe les informations par lots, selon un paramètre de sensibilité défini par l'utilisateur, puis fait un compte rendu.
C'est tout con, mais ca semble prometteur  :)  
 
Les versions à venir doivent pouvoir extraire les contenus désirés pour les écrire dans un fichier, et/ou faire une seconde analyse plus fine sur un lot particulier (2ieme voir 3ieme niveau d'analyse). Une fois fonctionnel, et si ca à un intérêt, je mettrais les sources en ligne.
 
Une bonne âme pour tester ? Je donne le script par MP, contre promesse de ne pas diffuser pour le moment.
 
Zaft
 
Edit : petite précision, ce script a pour vocation de pouvoir être utilisé à distance sur un serveur, sans ajout de paquets/modules. Il tourne donc avec un python de base.


Message édité par zaft le 03-06-2015 à 11:11:10
Reply

Marsh Posté le 03-06-2015 à 10:58:12   

Reply

Marsh Posté le 03-06-2015 à 18:44:23    

Je suis intéressé pour sa lecture et pour voir comment tu fais, mais je suis plutôt sur Perl donc pour le débug pur et dur faudra pas compter sur moi :D
 
Je suis intéressé pour la partie "présentation", car on trouve surtout de la mise en page au format HTML à exposer via un serveur web, or je suis plutôt à la recherche de quelque chose qui soit capable de basculer sur du XML, voire d’interagir automatiquement par l'envoi d'un mail suivant l'option choisie par l'admin.
 
Il pourrait être intéressant d'avoir un "mini forum" dédié, avec accès réservé pour pouvoir discuter entre testeurs et développeur :D


---------------
Grippe ? Coronavirus ? Portez votre masque correctement ! :D
Reply

Marsh Posté le 03-06-2015 à 19:18:57    

Fous le sur Github, et balance :P
 
Par contre, j'suis plus testeur, que dev.
du coup, j'te renvoie mes apprioris etc.  
Je ne peux pas te donner de lecon ;P


Message édité par feliwyn le 03-06-2015 à 19:21:01
Reply

Marsh Posté le 04-06-2015 à 11:51:23    

sans être intéressé par le script en lui meme, je vais quand meme poser la question : pourquoi réinventer la roue, et au passage la rendre carrée ? logwatch fait ça très bien deja.
 
si tu veux aller un peu plus loin qu'une machine, aujourd'hui le pattern classique des logs c'est celui du pipeline unique, et les consommateurs qui viennent se plugger dessus (analyzer, stockage, etc)


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 04-06-2015 à 13:38:27    

Tu dis:  
"pourquoi réinventer la roue, et au passage la rendre carrée ?"
 
C'est faut.
il existe multiple OS Linux. Pourtant, chacun à réinventer la roue. Partant du noyau, on a du Debian, du Arch, du BSD... Parfois, les roues sont plus ronde. Et souvent, plus adapter a différent type de personne.
(Pneu neige, pluie, course.. Ce sont tous des pneus, non? :) )

Reply

Marsh Posté le 04-06-2015 à 15:29:12    

feliwyn a écrit :

Tu dis:
"pourquoi réinventer la roue, et au passage la rendre carrée ?"

 

C'est faut.
il existe multiple OS Linux. Pourtant, chacun à réinventer la roue. Partant du noyau, on a du Debian, du Arch, du BSD... Parfois, les roues sont plus ronde. Et souvent, plus adapter a différent type de personne.
(Pneu neige, pluie, course.. Ce sont tous des pneus, non? :) )

 

Ton analogie est foireuse :spamafote:

 

Ce que je veux dire c'est qu'il y a fort à parier que son script est moins versatile et plus buggé que l'existant. Je n'ai meme pas parlé de portabilité du script entre les différents OS.
BTW, je fais juste part de mon XP, pour avoir pratiqué un peu la gestion de logs à des volumes "raisonnables" :o

 

edit : je dis pas que c'est mal d'écrire son propre soft, je le fais régulièrement pour répondre à des besoins précis non couverts par les différents softs existants


Message édité par black_lord le 04-06-2015 à 15:33:10

---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 04-06-2015 à 16:30:26    

Merci de vos retours.
 
bardiel et feliwyn je met le script directement ici finalement, il tourne mieux maintenant :)
Si le script est vraiment utile (automatisable), je rajouterai l'XML en sortie.
Ce n'est pas assez mature pour être mis sur GitHub, d'autant que c'est la première fois que j’utilise du python, le code est donc immonde et probablement non conforme à la philosophie du langage. Mais ça tourne pour le "proof of concept", c'est déjà ça.
 
Pour répondre à la question de l'utilité (je me suis posé la même, et je pose sur le forum aussi pour voir si ça peux servir), disons que j'utilise Logwatch quotidiennement, mais qu'il n'est pas capable de gérer certaines logs exotiques. Exemple : sur l'un des serveurs, nous avons du système de fichier Lustre. C'est particulièrement verbeux, et pour retrouver une erreur là dedans lorsque nous en suspectons une, c'est la croix et la bannière car le type d'erreur peut être différent à chaque fois (ce qui exclus le grep). De plus, logwatch nécessite l'installation d'un package et de ses quelques dépendances, ce qui est proscrit sur certaines de nos nodes, alors que python y est nativement dans sa version basique, d'où l'usage d'un script de ce type, que je peux pousser et utiliser à la volée par ssh sans avoir à rajouter autre chose.
J'ai donc bien conscience que l'outil n'a pas vocation à remplacer les existants, mais plutôt à s'adapter aux situations inhabituelles et répondre à une niche d'utilisateurs (dont je fait parti dans ce cas) pour une niche d'utilisation. :jap:
 
Voilà comment ça marche, le code suit :
 
Lancer le script avec la commande "python test.py" (en supposant que le fichier est nommé test.py).
Renseigner la position du log à lire (en supposant que le fichier est lisible, attention aux droits), et ne pas oublier les "" autour de la chaine.
Renseigner la valeur de sensibilité. Je recommande de tester 0.6 à 0.7 pour commencer, sinon ca fait trop de lots.
Ca mouline un peu.
Et ensuite le rapport affiche les lignes identifiées par lots de similarité et rangé dans l'ordre du plus présent au moins présent. Chaque ensemble se voit donner un numéro (tag). Dans cette vue là, il est déjà possible de voir si quelque chose de particulier se niche dans le log.
Ensuite plusieurs possibilités :
La fonction 0 (refaire l'analyse) ne marche pas, inutile d'essayer.
La fonction 1 (expand en lvl 2) n'est pas très intéressante, mais est fonctionnelle.
La fonction 2 (suppression de tags) est plus utile, dans mon usage en tous cas.
Chaque bloc affiché s'est vu donné un tag. Il est possible ainsi de supprimer certains blocs, notamment les plus gros qui correspondent souvent aux messages d'utilisation normale, et ainsi réduire à ce qui nous intéresse. Ensuite on écrit le log résultant. Et après, et bien si besoin, on peut refaire une analyse sur ce log (pour trier plus finement, en changeant le facteur de sensibilité (plus grand)), ou étudier le log à la main puisque qu'il est nettement plus court.
 
Attention aux yeux, c'est pas ergonomique et c'est moche :lol:

Reply

Marsh Posté le 04-06-2015 à 16:31:44    

Le code :
 

Code :
  1. # Generic Log analyser v1.0
  2. # Zaft
  3.  
  4. # To use this script, set the logfile name and location,
  5. # and adjust 'match' variable between 0 and 1 (0.7 and 0.8 are good)
  6.  
  7. logfile = input('Enter log file position (ex "/var/log/auth.log", do not forget brackets) :\n')
  8. #logfile="log4"
  9. match = input('Enter sensibility value (match factor), between 0 and 1 (0.6 to 0.7 is a good starting range of values) :\n')
  10. #match=0.7
  11.  
  12. # Import sys
  13. import sys
  14. sys.stdout.flush()
  15.  
  16. # Import and define sequence matcher
  17. from difflib import SequenceMatcher
  18. def similar(a, b):
  19.    return SequenceMatcher(None, a, b).ratio()
  20.  
  21. # Open log file
  22. with open (logfile, "r" ) as myfile:
  23.    data = myfile.readlines()
  24.  
  25. # Allocate memory
  26. datasize = len(data)
  27. data_tag = range(datasize)
  28.  
  29. knowndata_s = range(datasize) # more than needed, to be optimized
  30. knowndata_tot = range(datasize) # same
  31.  
  32. # Init first patern
  33. knowndatasize = 1
  34. knowndata_s[0] = data[0]
  35. knowndata_tot[0] = 1
  36.  
  37. flag = 0
  38. c = 0
  39.  
  40. print
  41. print 'Analysing....  ',
  42.  
  43. # Loop on all lines of file
  44. for i in range (1,datasize):
  45.   # Check if data is already registered as patern
  46.    # Loop on all already known patern
  47.    for j in range (0,knowndatasize):
  48.        if similar(data[i],knowndata_s[j]) > match: # 0.8 seems good for auth.log
  49.            # Data already known, increment and skip to next data
  50.            knowndata_tot[j] = knowndata_tot[j] + 1
  51.            data_tag[i] = j
  52.            flag = 1
  53.            break
  54.    # Data not already registered, create a new patern
  55.    if flag == 0:
  56.        knowndata_s[knowndatasize] = data[i]
  57.        knowndata_tot[knowndatasize] = 1
  58.        data_tag[i] = knowndatasize
  59.        knowndatasize = knowndatasize + 1
  60.    else:
  61.        flag = 0
  62.  
  63.    # Display work in progress
  64.    if c == 20:
  65.        sys.stdout.write('\b/')
  66.    elif c == 40:
  67.        sys.stdout.write('\b-')
  68.    elif c == 60:
  69.        sys.stdout.write('\b\\')
  70.    elif c == 80:
  71.        sys.stdout.write('\b|')
  72.        c = 0
  73.    sys.stdout.flush()
  74.    c = c + 1
  75.  
  76. print '\b\b done!'
  77.  
  78.  
  79. print 'Sorting results....  ',
  80. knowndata_tag = range(knowndatasize)
  81. # Sort results for display only
  82. knowndata_tot_d, knowndata_s_d = (list(t) for t in zip(*sorted(zip(knowndata_tot[0:knowndatasize], knowndata_s[0:knowndatasize]))))
  83. knowndata_tot_d, knowndata_tag_d = (list(t) for t in zip(*sorted(zip(knowndata_tot[0:knowndatasize], knowndata_tag[0:knowndatasize]))))
  84. print '\b\b done!'
  85.  
  86. # Print results
  87. print
  88. print "########################################################"
  89. print "############# Found ",knowndatasize," different paterns"
  90. print "#####"
  91. print
  92.  
  93. for j in range (0,knowndatasize):
  94.    print "----> tag :",knowndata_tag_d[j]," found ",knowndata_tot_d[j], " time(s) : ", knowndata_s_d[j]
  95.  
  96. # Extract desired tag for lvl 2 analysis
  97.  
  98. #while exit
  99. print
  100. print "What do you want to do ?"
  101. print "0 . Redo analysis with a different match parameter"
  102. print "1 . Lvl 2 analysis (redo analysis on part or previous analysis to expand a specific part)"
  103. print "2 . Purge log from specific lines and write result to file"
  104. #print "      Note : you can redo an analysis on this file after with a different match parameter to expand"
  105. value = input("      Note : you can redo an analysis on this file after with a different match parameter to expand\n" )
  106.  
  107. if value == 2:
  108.    flag = 0
  109.    data_tag_remove = range(knowndatasize)
  110.    rm = 0
  111.    data_tag_remove[0] = input("Which tag do you want to remove ?\n" )
  112.    while flag == 0:
  113.        value = input("Which tag do you also want to remove ? (-1 to print current state, -2 validate and write)\n" )
  114.        if value == -2:
  115.            flag = 1
  116.        elif value == -1:
  117.            print
  118.            print "########################################################"
  119.            print "############# Update"
  120.            print "#####"
  121.            print
  122.            print "Tags to be removed :",data_tag_remove[0:rm]
  123.            print
  124.            print "To be written :"
  125.            print
  126.            for j in range (0,knowndatasize):
  127.                flag1 = 0
  128.                for i in range (0,rm+1):
  129.                    if knowndata_tag_d[j] == data_tag_remove[i]:
  130.                        flag1 = 1
  131.                if flag1 == 0:
  132.                    print "tag :",knowndata_tag_d[j]," found ",knowndata_tot_d[j], " time(s) : ", knowndata_s_d[j]
  133.        else:
  134.            rm = rm + 1
  135.            data_tag_remove[rm] = value
  136.    filename = input('Enter file name and position (ex : "/home/sphen/log.out" , do not forget brackets) :\n')
  137.    print 'Writing to file....  ',
  138.    with open (filename, "w" ) as myfile2:
  139.        for i in range (0,datasize):
  140.            flag = 0
  141.            for j in range (0,rm+1):
  142.                if data_tag[i] == data_tag_remove[j]:
  143.                    flag = 1
  144.            if flag == 0:
  145.                myfile2.write(data[i])
  146.    print '\b\b done!'
  147.    quit()
  148.  
  149. elif value == 1:
  150.    l2_tag = input("Which tag for lvl 2 analysis ?\n" )
  151.    print "Which match for lvl 2 analysis ? Must be > ",match
  152.    l2_match = input("\n" )
  153.    c = 0
  154.  
  155.  
  156.    # Extract lvl 2 data from lvl 1 data
  157.    l2_datasize = knowndata_tot[l2_tag]
  158.    l2_data = range(l2_datasize)
  159.    for i in range (0,datasize):
  160.        if data_tag[i] == l2_tag:
  161.            l2_data[c] = data[i]
  162.            c = c + 1
  163.  
  164.    l2_knowndata_s = range(l2_datasize) # more than needed, to be optimized
  165.    l2_knowndata_tot = range(l2_datasize) # same
  166.  
  167.    # Init first patern
  168.    l2_knowndatasize = 1
  169.    l2_knowndata_s[0] = l2_data[0]
  170.    l2_knowndata_tot[0] = 1
  171.  
  172.  
  173.    c = 0
  174.  
  175.    print
  176.    print 'Analysing l2....  ',
  177.  
  178.  
  179.    for i in range (1,l2_datasize):
  180.       # Check if data is already registered as patern
  181.        # Loop on all already known patern
  182.        for j in range (0,l2_knowndatasize):
  183.            if similar(l2_data[i],l2_knowndata_s[j]) > l2_match: # 0.9 seems good for auth.log
  184.                # Data already known, increment and skip to next data
  185.                l2_knowndata_tot[j] = l2_knowndata_tot[j] + 1
  186.                flag = 1
  187.                break
  188.        # Data not already registered, create a new patern
  189.        if flag == 0:
  190.            l2_knowndata_s[l2_knowndatasize] = l2_data[i]
  191.            l2_knowndata_tot[l2_knowndatasize] = 1
  192.            l2_knowndatasize = l2_knowndatasize + 1
  193.        else:
  194.            flag = 0
  195.  
  196.        # Display work in progress
  197.        if c == 4:
  198.            sys.stdout.write('\b/')
  199.        elif c == 8:
  200.            sys.stdout.write('\b-')
  201.        elif c == 12:
  202.            sys.stdout.write('\b\\')
  203.        elif c == 16:
  204.            sys.stdout.write('\b|')
  205.            c = 0
  206.        sys.stdout.flush()
  207.        c = c + 1
  208.  
  209.    print '\b\b done!'
  210.  
  211.    print 'Sorting results l2....  ',
  212.    # Sort results for display only
  213.    l2_knowndata_tot_d, l2_knowndata_s_d = (list(t) for t in zip(*sorted(zip(l2_knowndata_tot[0:l2_knowndatasize], l2_knowndata_s[0:l2_knowndatasize]))))
  214.    print '\b\b done!'
  215.  
  216.    # Print results
  217.    print "###############################"
  218.    print "# Found ",l2_knowndatasize," different paterns"
  219.    print "###############################"
  220.    for j in range (0,l2_knowndatasize):
  221.        print " found ",l2_knowndata_tot_d[j], " time(s) : ", l2_knowndata_s_d[j]


 
 
edit coloration syntaxique // black_lord


Message édité par zaft le 05-06-2015 à 14:08:31
Reply

Marsh Posté le 04-06-2015 à 16:50:26    

zaft a écrit :

ce qui est proscrit sur certaines de nos nodes, alors que python y est nativement dans sa version basique, d'où l'usage d'un script de ce type,


Comme Black_Lord, généralement les logs ça s'exporte. Les analyses se font sur d'autre machines faites pour cela avec les apps et les ressources pour cela.
 


---------------
Relax. Take a deep breath !
Reply

Marsh Posté le 04-06-2015 à 16:56:24    

Certes, vous marquez un point là dessus ;)

Reply

Marsh Posté le 04-06-2015 à 16:56:24   

Reply

Marsh Posté le 04-06-2015 à 17:44:43    

C'est surtout une des bases. une des raisons est que si ta machine crashe, t'es content d'avoir les logs ailleurs. Tu as plein d'autres raisons de le faire : remplissage des disques locaux, leur utilisation (== perfs), la centralisation des infos, la sécurité (machine compromise). Cette liste c'est juste les premiers trucs qui me viennent à l'esprit.
 
Syslog fait ça très, et je ne connais aucun admin qui ne fasse pas ça.
 
Dans un cas comme le tien, c'est encore plus utile. tu n'as ton script à deployer qu'une fois (par collecteur on va dire). du coup tu peux te permettre des choses plus fancy au niveau des deps aussi. Bref, au delà du sujet du script, tu devrais penser à envoyer tes logs en remote.


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 04-06-2015 à 22:06:35    

Ce n'est pas moi qui ai déployé ces machines, mais aujourd'hui les logs sont éparpillées sur les nodes (à noter qu'il y a des centaines de nodes). Sur une autre machine, a été utilisé un montage NFS, mais personnellement ca m'a semblé délirant.
Pour le moment, je rapatrie les logs par ssh, avec un user particulier qui fait un sudo cat sur les logs. Mais j'ai commencé à réaliser qu'il existe de nombreux outils (souvent plus viables que les scripts maisons) et qu'il est dommage de s'en priver.
 
Le fonctionnement de syslog répond effectivement parfaitement et simplement à ce problème. Je vais soumettre l'évolution et le déployer.
 
Bon et ce script d'analyse alors, ca vous semble utile ? Pour tracker un évènement particulier dans des logs non prises en charge par logwatch ? :D
 
Edit : d'ailleurs je pense que je ne vais pas tarder à soumettre un topic où j'exposerai comment je fait pour administrer mes machines, et où vous pourrez vous donner à coeur joie de démonter mon oeuvre et de m'indiquer des solutions plus propres. :jap:

Message cité 1 fois
Message édité par zaft le 04-06-2015 à 22:21:17
Reply

Marsh Posté le 05-06-2015 à 12:11:02    

zaft a écrit :

Ce n'est pas moi qui ai déployé ces machines, mais aujourd'hui les logs sont éparpillées sur les nodes (à noter qu'il y a des centaines de nodes). Sur une autre machine, a été utilisé un montage NFS, mais personnellement ca m'a semblé délirant.
Pour le moment, je rapatrie les logs par ssh, avec un user particulier qui fait un sudo cat sur les logs. Mais j'ai commencé à réaliser qu'il existe de nombreux outils (souvent plus viables que les scripts maisons) et qu'il est dommage de s'en priver.


 
[:hide]
 
[:hide][:hide][:hide]
 
des centaines de nodes, rassure moi : (tu|vous) utilise(s|z) un système de config management ?
 

zaft a écrit :


Le fonctionnement de syslog répond effectivement parfaitement et simplement à ce problème. Je vais soumettre l'évolution et le déployer.


 
C'est désigné pour :o
 

zaft a écrit :

Edit : d'ailleurs je pense que je ne vais pas tarder à soumettre un topic où j'exposerai comment je fait pour administrer mes machines, et où vous pourrez vous donner à coeur joie de démonter mon oeuvre et de m'indiquer des solutions plus propres. :jap:


 
par curiosité, tu as quelle XP en tant que sysadmin ?


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 05-06-2015 à 14:12:10    

Je suggère que l'on discute de ça par MP, ca sort du cadre du topic.
 
Je te répond de suite par MP.

Reply

Marsh Posté le 05-06-2015 à 14:14:22    

ok :o


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed