Annonce

Réduire
Aucune annonce.

Script de recherche dans les logs serveur

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Script de recherche dans les logs serveur

    Salut à tous ! Je suis une grosse bite en PHP, c'est assez sévère. Mais comme je suis débrouillard, j'arrive toujours à mes fins.
    Bref, je voulais partager avec vous un bout de code que j'ai écrit tout à l'heure qui permet de rechercher un terme dans ses logs afin d'en connaitre le nombre d'occurrence. Je suis probablement le seul pélo à avoir besoin de ça, mais moi j'aime bien. Par exemple, combien de fois a été téléchargé tel fichier ? On recherche le nom du fichier et hop ! Evidemment on est limité par le temps des logs, et on ne peut pas savoir sur une année ou sur tout le temps. J'imagine que ca existe, avec un fichier d'incrémentation par exemple (tiens, idée ?), mais c'est pas le but ici.

    C'est vraiment pas grand chose, mais je me dit que ca peut donner des idées, ou aider quelqu'un qui débute.

    Je vous en prie, critiquez, améliorez, discutez !

    Code:
    <?php
    $search = $_GET['search']; // Read variable from URL
    if ($search == "") { // If var $search is empty,
    $search = "No search entered"; // give it a value
    $num ="0"; // and this one too, that avoid doing stuff for nothing
    }
    else {
    $num = shell_exec("cd ~/logs/; cp ./access.log.*.gz ~/comax/logs; cp ./access.log.current ~/comax/logs; cd ~/comax/logs; cd ~/comax/logs; gunzip -f ./*.gz; cat ./* | grep -a -i $search | awk 'END {print NR}'; rm ./*"); // Yeah, I love bash. If there is another way, let me know. I'll develop that later on, but it's quite easy.
    }
    ?> // we're pretty much done.
    <html> // obviously...
    <head></head>
    <body>
    <FORM NAME ="test" METHOD ="GET" ACTION = "countme.php"> <!-- we use GET method because that's how $serch is read. Could have been POST too though. Action is the page that will be loaded. This designates the very page we're on in this case. -->
    <INPUT TYPE = 'text' VALUE ='<? echo("$search"); ?>' NAME = 'search'><!-- value is what's in the textbox, so it's prettier if it dynamically change with the search so that it doesn't default everytime. Name = search is important, that's what is used for the URL -->
    <INPUT TYPE = 'Submit'> <!-- just to have a button, but useless really. Just for pretty stuff. -->
    </FORM>
    <div id ='display'>There are <? echo("$num"); ?> results for <? echo("$search"); ?>.</div>
    </body>
    </html>
    Maintenant, pour le code bash : c'est le code écrit sur une ligne qui est passé à shell_exec() dans le code php. Je l'ai mis ici sur plusieurs lignes pour plus de lisibilité. Le code va rechercher dans vos logs serveur.
    Il pourrait bien être différent pour vous, il faut l'adapter, mais l'idée est là :

    Code:
    #! /bin/bash
    cd ~/logs/ # Go to home folder, then logs
    cp ./access.log.*.gz ~/comax/logs #we can't work in that folder, so we copy over to a place where we can.
    cp ./access.log.current ~/comax/logs #same. Make sure destination folder exists. I didn't mkdir because it already exists for me.
    cd ~/comax/logs #Go to our working folder
    gunzip -f ./*.gz #Unzip everything in the folder
    cat ./* | # read everything and pipe to...
    grep -a -i $search | #grep, that will search vor the php variable we defined in the php script, and pipe to...
    awk 'END {print NR}' #awk, that will count how many lines there are, in the end to avoid massive useless output.
    rm ./* #delete all that shit.
    
    
    #That not very pretty, but it does its job !
    @Saka/Mactux : il existe pas des balises genre [php] pour avoir la coloration et tout ?

    Enfin, "désolé" pour les commentaires de codes en anglais, mais c'est comme ça que je fais, même quand ce n'est que pour moi.

    Je vous invite tous à faire comme moi et à balancer vos de scripts, même pourris. Perso j'aime lire des scripts courts et bien commenté, c'est ce qui m'aide le plus !

    Précisions : d'aucuns pourraient penser que le fait de passer de l'user input directement à un shell_exec pourraient être dangereux sans contrôle, mais j'ai fait quelques tests, et je n'ai pas trouvé de valeurs qui fasse planter le truc. Les guillemets sont échapées automatiquement, et un pipe fait planter mais ne permet pas d'en faire plus. Et de toute façon c'est planqué sur mon site, personne n'y a accès.

    Exemple en image :


    Dans cet exemple, je sais qu'il y a eu 168 accès aux différents fichiers flv de mon serveur. Je pourrais bien sur être plus précis en mettant le nom d'une seule vidéo. Si j'ai blackout le truc, c'est pour éviter les malins qui rechercheraient en boucle des chaines de caractères de plusieurs milliers de caractères.
    Dernière modification par comaX, 17 janvier 2012, 16h14.

  • #2
    Salut Comax,

    J'ai pas bien capté quel est le but de ton code.

    Tu recherches tous les fichiers *.log dans ton disque et recherche les occurences d'un mot dans chaque fichier?

    Commentaire


    • #3
      Grosso merdo, voui !

      C'est assez vulgaire, je te l'accorde, mais ça marche assez vite pour moi

      Exemple en image :
      recherche.PNG

      Dans cet exemple, je sais qu'il y a eu 168 accès aux différents fichiers flv de mon serveur. Je pourrais bien sur être plus précis en mettant le nom d'une seule vidéo.

      [HS]j'ai appris pour l'équipe, trop de taff ? [/HS]
      Dernière modification par comaX, 17 janvier 2012, 16h11.

      Commentaire


      • #4
        python c'est plus rapide que PHP, non?

        Code:
        for root, dirs, files in os.walk("/"):
            for file in files:
                path = os.path.join(root, file)
                    if file.endswith('.log'):
                        liste.append(file)
        print liste # liste de tout les fichiers log
        Execute ce code en admin, pour avoir tous les fichiers log, pour la suite, ça ne devrait pas te poser de soucis je pense, sinon dis le

        sudo fichier.py
        [HS]Oui beaucoup de taff en effet, demain commence une sacré course, qui ne va s'arrêter que samedi, oufff...[/HS]

        Commentaire


        • #5
          PHP n'exécute que dalle quasiment, et le but est d'afficher ça dans une page web. Comme ça quand je distribue des trucs sur internet, je peux savoir directement avec une simple recherche sur mon site si ca marche ou non, et ajuster en fonction... Je tiens à préciser que je ne "distribue" rien de bizarre, quelques vidéos de culs de façon à "payer" des camarades qui m'aident dans certaines recherches

          Sinon, c'est bash qui s'occupe de bidouiller les fichiers sur le serveur, et je n'ai pas la moindre idée de ce qui est plus rapide ou non entre bash et python pour ce genre de taches...

          Quoi qu'il en soit, merci pour ce bout de code, ça peut toujours être utile !
          Dernière modification par comaX, 17 janvier 2012, 16h52.

          Commentaire


          • #6
            Quoi qu'il en soit, je t'apporte une petite contribution, non web (mais c'est possible) car la flemme de me mettre dans un framework, te permettant d'avoir le résultat du nombre d'occurence, sans changer quoique se soit dans ton fichier de base (confortable non?).

            il est pas optimisé, si j'ai le temps je l'améliorerais, mais il est déjà bien rapide sans artifices, voilà le partage

            Code:
            #!/usr/bin/env python2.7
            # -*- coding:utf8 -*-
            
            import os, fnmatch, sys
            from collections import defaultdict
            
            class Searching(object):
                def __init__(self):
                    self.dico = defaultdict(int)
                    self.lines, self.files = [], []
                    self.liste_mot = raw_input('Entrer vos mots a rechercher : ').split()
                    self.liste = self.gen()
                    self.search()
            
                def gen(self):
                    """Génère la liste des fichiers du type log dans une liste"""
                    liste_files = []
                    for root, dirs, files in os.walk("/"):
                        for file in fnmatch.filter(files, '*.log'):
                            try:
                                liste_files.append(os.path.join(root, file))
                            except: pass
                    return liste_files
            
                def affiche_stat(self):
                    """Affiche la statistique des mots trouvés"""
                    for k, v in self.dico.items():
                        print "le mot {0} est trouvé {1} fois".format(k, v)
            
                def affiche_lines(self):
                    """Affiche les lignes où se trouvent les mots recherchés"""
                    for num, ligne in enumerate(self.lines):
                        print "ligne {0} --> {1}".format(num+1, ' '.join(ligne))
            
                def affiche_files(self):
                    """Affiche les fichiers où les mots ont été trouvés"""
                    print "les fichiers concernés sont :"
                    print "---------------------------
                    for file in self.files:
                        print file
            
                def search(self):
                    """Retourne le dictionnaire incluant les mots et les stats"""
                    for files in self.liste:
                        with open(files, 'r') as f:
                            lines = [line.strip() for line in f.readlines(1024)]
                            if lines:
                                for line in lines:
                                    line = line.split()
                                    for word in self.liste_mot:
                                        self.dico[word] += line.count(word)
                                        if word in line:
                                            self.files.append(files)
                                            self.lines.append(line)
                    return self.dico
            
                def __str__(self):
                    return repr(self.dico)
            
            def menu():
                print """(A)fficher les statistiques
            a(F)ficher les lignes concernées
            aff(I)cher les fichiers concernés
            (Q)uitter"""
                choix = raw_input("Entrer votre choix : ").lower()
                if choix not in "afiq":
                    raise ValueError("Choix incorrect")
                return choix.lower()
            
            def main():
                while True:
                    choix = menu()
                    if choix == "a":
                        s.affiche_stat()
                    elif choix == "f":
                        s.affiche_lines()
                    elif choix == "i":
                        s.affiche_files()
                    else:
                        sys.exit("Program quit")
            
            s = Searching()
            main()
            Exemple d'exécution

            [email protected]:~/Bureau$ sudo python test.py
            Entrer vos mots a rechercher : key fred1599 coucou bonjour hello
            {'bonjour': 0, 'fred1599': 36, 'coucou': 0, 'hello': 0, 'key': 46}
            Voilà bon amusement
            Dernière modification par fred, 17 janvier 2012, 22h03.

            Commentaire

            Chargement...
            X