IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

decoupage d'un fichier log


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut decoupage d'un fichier log
    Bonjour. Je suis actuellement en stage et dans le cadre de mon BTS nous avons convenu avec mon tuteur que mon projet serai le suivant :

    creation d'un script en PERL pour analyser les log du firewall en place.

    Personnellement je n'avais quasiement jamais touché a PERL (j'en profite pour conseiller aux debutants PERL pour l'impatient aux edition H&K que j'ai trouvé pour moins de 10€. Il est simple, petit et vas droit à l'essentiel)

    donc j'arrive a mon petit soucis :

    J'ai commencé par me faire un peut la main sous perl en creeant un petit script qui se contentait de lire un fichier contenant des informations separé par une tabulation et qui generai une page HTML contenant les information dans un tableau. jusque la : pas de soucis !

    Je me suis donc dis "nikel ! il y a plus qu'a adapter le script au format du fichier log du firewall".

    Sauf que là : tout se complique !

    en effet le log généré par le firewall n'est pas un beau fichier contenant du texte bien rangé avec un separateur constant mais plutôt quelque chose de se type :


    Mar 23 04:19:23 192.168.XX.XX IP-Logs: FIREWALL - id=firewall time="2006-03-23 04:19:20" fw=firewall.domaine.com type=IP src=192.168.XX.XX dst=192.168.XX.XX etc ....
    impossible donc de faire un decoupage propre.

    De toute façon toutes les information ne sont pas utiles. Je voudrais juste recuperer les lignes dont (par exemple) la destination ne serai pas une IP du type 192.168.XX.XX (j'espere que je ne suis pas trop confus je commence a m'embrouiller moi même ...)

    Aprés avoir fureté un long moment sur le forum je me dis "bon sang mais c'est bien sur ! je vais utiliser GREP !!"


    je lis donc le fichier ouvert precedement ligne par ligne et je recherche une expression qui correspond à "dst=" + "ip autorisée" que je place ensuite dans un tableau.



    while ($line = <DATA>)
    {
    print OUT "<tr>\n";
    $line;
    $dstip = grep(/dst\=192\.168\.\d\d?\d\.\d\d?\d/, $line);
    {
    print OUT "<td style='font-weight: bold; color: rgb(0, 0, 0);'>$dstip</td>\n";
    print $dstip;
    }

    j'ai rajouté "print $dstip;" afin de voir pendant l'execution se que le script me trouve et la horreur : il ne me trouve que "1" et se pour chaque ligne ...

    je dois certainement avoir fais une erreure au niveau de mon code. Quelqu'un aurai une idée sur la question ?




    ------------------------
    edit
    ------------------------

    Je viens de me rendre compte d'une erreure :

    Si j'utilise grep, le script vas chercher dans la liste l'expression souhaitée et au lieu de recuperer juste l'element que je souhaite, il vas me sortir toute la ligne contenant l'element ... Il vas faloir qu je trouve autre chose ...

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Par défaut
    Bonjour makubex,

    Utilise les expressions régulières, il y a un très bon cours sur la Faq Perl

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut
    j'etais justement en train de modifier mon code au moment de ta reponse ^^
    J'ai donc utilisé le systeme de l'expression reguliere pour detecter si une de mes adresses de destination ne correspond pas a la regle definie soit :


    while ($line = <DATA>)
    {

    if ($line !~ /dst\=192\.168\.\d\d?\d\.\d\d?\d/) {
    print " $line ";
    }
    j'ai modifié le fichier de log que j'utilise pour mes test et il m'a bien trouvé un e ligne ne respectant pas la regle et me l'a affiché.

    Merci pour ton aide ^^


    J'en viens maintenant a mon deuxieme probleme : decouper efficacement mon fichier afin d'ameliorer le traitement des données ...

    en effet une fois l'erreure trouvée je voudrais l'afficher sur une page intranet (simple tableau généré en html rien de compliqué). Pour cela, il va faloir que je decoupe ma ligne et que je la place dans des collones differents. Le soucis viens du format de la ligne :


    Mar 23 04:19:23 192.168.XX.XX IP-Logs: FIREWALL - id=firewall time="2006-03-23 04:19:20" fw=firewall.domaine.com type=IP src=192.168.XX.XX dst=192.168.XX.XX
    et il ne s'agis la que d'un extrait.


    Se que je pense faire c'est d'abord faire un premier passage qui selectionne que les lignes interessantes et les place dans une liste (ou un fichier temporaire je ne sais pas encore) ensuite un deuxieme passage decoupe les lignes les place dans un tableau et genere le fichier html (et eventuellement envoi le lien vers la page par mail).

    Par contre voilà mon petit soucis : comment decouper ma ligne. Comme je l'ai precedement expliqué je ne peut pas me contenter d'un

    @table = split " ",$line;
    car la ligne n'a pas de separateur regulier. Sur se point j'avoue etre un peut paumé ...

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Par défaut
    Tu peux peut-être regarder avec la fonction substr(), qui permet d'extraire une chaine de caractères en fonction des positions (pour la date déjà).
    Es tu sur que le fichier n'est pas structuré ? As tu une doc sur la log de ton firewall ?

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut
    pour le moment toutes la seule info dot je dispose c'est le log en lui même. En fait il est bien structuré mais pas de façon reguliere. Les separateurs sont tanto des espaces tanto des = etc ...

    toujous est-il que je vais commencer a me pencher sur la fonction substr() merci ^^

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Par défaut
    Il faudra peut-être faire un mixe de et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    substr($_,$position,$long);

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut
    alors ...

    Je ne connaissais pas la fonction substr() et j'avoue qu'elle m'aide franchement. En utilisant cette fonction je me suis débarassé de la date et des information en trop dans mon fichier.
    Une fois les 45 caracteres en moins, je me retrouve avec une ligne plus "propre" respectant la regle suivante :

    rubrique=resultat suivis d'un espace et ainsi de suite.

    bon jusque la je me dis "super il ne reste plus qu'a mettre en pratique les information que l'on m'a donné sur le forum et c'est bon !"

    or (descidement j'ai pas de bol !) certain resultat contiennent des espaces. Je ne peut donc pas utiliser l'espace comme separateur et

    split(/ /,$_)
    tombe a l'eau ...

    je pense que vu que les rubriques ne varient pas je vais essayer de faire un tri au fure et a mesure, rechercher une rubrique et selectionner les donnée allan du signe "=" jusqu'au nom de la rubrique suivante ....

    les fichiers log sont assés volumineux en fin de journée mais si je ne traite que les lignes qui seront selectionnés ça devrais aller.
    ar la suite je pense que le plus simple serai de tout stocker dans un fichier txt avec un separateur unique et de faire une page web qui recupere les informtions du fichier texte .....

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 210
    Par défaut
    Essaie plutot

  9. #9
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Je ne suis pas sûr que tu ais vraiment besoin de parser l'intégralité de la ligne : a priori, il te suffit de faire une ou deux regex pour récupérer les infos qui t'intéresse.

    --
    Jedaï

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut
    J'ai pensé utiliser les regex mais je galere quelque peut ...

    utiliser une expression du type :

    \S\=
    pour rechercher une expression suvi du signe = afin de rechercher chaque identifiant et je me suis dis qu'il sufisais ensuite d'utiliser

    \w
    pour selectionner la valeur qui suis. cela dis etant donné que certaines valeurs sont des phrases, l'expression reguliere \w ne fonctionnera pas il faudra plustot que j'utilise quelquechose du type


    \w*^\=
    pour selectionner une suite de mots dont le dernier n'est pas suivi du signe =



    donc en resumé il faut que j'utilise l'expression :

    \S*\=\w*^\=
    pour selectionner l'expression complete et que je tronque ensuite la partie située avant le signe =


    quelqu'un peut confirmer mes dires ?



    ---------------------
    EDIT
    ---------------------

    je vais faire un petit resumé de la situation en cour ... au passage je tiens a remercier tout ceux qui prenent sur leur temp pour m'aider. C'est un acte qui est trop rare de nos jours pour ne pas etre signalé !


    donc j'ai un fichier de log contenant une liste de lignes du type :

    Mar 23 04:19:23 192.168.XX.XX IP-Logs: FIREWALLLOG - id=firewall time="2006-03-23 04:20:01" fw=firewall.domaine.com pri=6 type=IP gmtime=1143084001 ip_log_type=ENDCONN src=192.168.XX.XX dst=192.168.XX.XX proto="822/tcp" protocol=6 port_src=65000 port_dst=132 intf_in= intf_out= nat=NO snat_addr=0 snat_port=0 dnat_addr=0 dnat_port=0 sent=237 rcvd=401 end_reason="Closed after reset"
    Je commence par selectionner seulement les lignes que je souhaite voir resortire. Par exemple celle dont l'adresse de destination ne correspond pas au plan d'adressage IP en vigueure :

    while ($line = <DATA>)
    {
    print OUT "<tr>\n";
    if ($line !~ /dst\=192\.168\.\d\d?\d\.\d\d?\d/)
    je me retrouve donc avec une ligne qui m'indique que l'ip de destination n'est pas bonne (voir plus haut).

    je prend ma ligne et commence par tronquer les premieres information afin d'avoir une ligne plus homogene :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $line = substr ($line, 50);
    j'ai donc maintenant une ligne qui se compose comme ceci :

    identifiant=valeur

    je souhaite tronquer les identifiant (soit tout se qui se trouve avant le signe =) et placer chaque valeur dans un tableau pour l'afficher ensuite dans une page web.

    ici tout se corse : je pensais faire quelque chose du type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @tbl = split (/^\s*\=/, $line);
    en se faisant je pensais que ma ligne serai decoupé avec comme separateur n'importe quel nombre de charactere sauf un espace suivi d'un egual mais visiblement ça ne fonctionne pas ...

    Il dois forcement y avoir un probleme quelque part ...

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut
    bon finalement tout s'arrange : j'ai trouvé comment faire !

    je vais simplement utiliser une expression reguliere et j'aurai besoin que quelqu'un puisse me confirmer qu'elle soit correcte.


    je souhaite effectuer un "split" et placer chaque partie dans un tableau different. Chaque partie est separée par un espace donc jusque là : pas de problemes :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @tabl2 = split /\s/, $line;
    probleme : certaine donnée sont des phrases entre guillemet du type "xyz not found"
    Or si j'utilise l'expression ecrite plus haut je me retrouve avec

    au lieu de

    Je me suis donc dis : "no problems" je vais faire une expression qui split les espaces sauf si ceux-ci sont entourés de guillemets
    J'ai donc ecris ça :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @tabl2 = split /\s[^"\.*"]/, $line;
    en se faisant je pensais que l'expression rechercherai un espace en evitant un "nombre quelconque de charactere quelconque" entre guillemets. Mais visiblement ça ne fonctionne pas ...

  12. #12
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Tu fais visiblement quelques confusions au niveau des expressions régulières : le '^' représente normalement un début de ligne, et ce n'est qu'entre [] qu'il prend un sens de complémentaire, d'ailleurs il s'agit uniquement d'une classe de caractère : un [] représente toujours un seul caractère, dont on spécifie ce qu'il peut être.
    Dans ton cas tu peux essayer ce split :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    split /\s+(?![^"=]*")/, $line;
    Que fait-il ? Il splite sur tous les espaces, qui ne sont pas suivi par n'importe quelle suite de caractères sauf des '=' ou des '"', puis un guillemet. Il semble marcher.

    --
    Jedaï

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut
    super ça fonctionne ! j'avoue que j'ai encore un peut de mal a comprendre l'expression reguliere que tu m'a donné.

    Bien que le resultat soit là j'aimerai tout de même comprendre afin de ne plus faire se genre d'erreure ...

    donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    split /\s+(?![^"=]*")/, $line;

    \s+ -->un espace ou plus

    ?! --> je ne comprend pas

    [^"=]* --> ni un " ni un = un nombre quelquonque de fois (voir 0)

    ")/ --> terminé par un "

    c'est bien ça ?

  14. #14
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Le (?!regex) est ce que l'on appelle look-ahead négatif ("coup d'oeil vers l'avant" négatif). Si une regex contient un tel groupement, le moteur de regex tente de matcher la regex à l'intérieur à l'endroit où se trouve le groupement, si il y arrive, ce match échoue, sinon le match réussit (pourvu que le reste de la regex marche) mais ne contient que ce qui a été matché en-dehors du look-ahead.
    Autrement dit, ma regex matche uniquement un ou des espaces (\s*) mais elle ne les matche que si ils ne sont pas suivis d'un guillemet, avant tout autre '='.

    Les look-ahead et les look-behind (négatifs comme positifs) sont des outils extrèmement puissants et utiles dans bien des cas.

    --
    Jedaï

Discussions similaires

  1. [Log4j]Cherche visualiseur de fichiers logs de log4j
    Par RolandB dans le forum Logging
    Réponses: 9
    Dernier message: 18/03/2009, 16h11
  2. Programme qui analyse un fichier log
    Par abdou.sahraoui dans le forum Entrée/Sortie
    Réponses: 9
    Dernier message: 20/08/2004, 15h27
  3. Decoupage d'un fichier texte avec cut
    Par tesla dans le forum Linux
    Réponses: 3
    Dernier message: 28/06/2004, 16h39
  4. Fichier log des requêtes d'une bdd
    Par Sub0 dans le forum Administration
    Réponses: 4
    Dernier message: 22/03/2004, 15h12
  5. [] [Stratégie] Comment créer un fichier log
    Par Skeezo dans le forum Installation, Déploiement et Sécurité
    Réponses: 4
    Dernier message: 16/09/2002, 19h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo