Salut les regex !
J'ai souvent à parser des gros fichiers en tentant de matcher par rapport à une liste.
Du coup je me retrouve souvent à faire des doubles boucles bien dégueulasses et bien gourmandes en ressources.
En gros j'aimerais savoir (en Python ou en Perl), comment faire ça de manière en plus élégante et moins "brutale", de préférence en évitant d'aller charger des modules externes ça serait le top, pis si ça pouvait rester lisible aussi, parce que je vous connais les brutos du Perl …
@mon_log = open(LOG,</mon/chemin/log);
@ma_grosse_liste_IP;
foreach $ligne @mon_log
{
foreach $IP @ma_grosse_liste_IP
{
//Match de mon ip dans la log et traitement ...
}
}
Merci à vous.
# Le type "set" ?
Posté par Zylabon . Évalué à 5.
J'y connais rien en perl, mais en python ya ça :
https://docs.python.org/3/library/stdtypes.html#frozenset
Ça te ferait passer de O(taille_ficher * taille_liste) à O(taille_liste + taille_fichier), en supposant que ce soit implémenté avec une table de hash (ils font chier à pas mettre les complexité).
Please do not feed the trolls
[^] # Re: Le type "set" ?
Posté par lolop (site web personnel) . Évalué à 3.
Je pertinente, à condition que sa grosse liste IP tienne en mémoire.
Une fois chargée en mémoire la liste IP sous forme de
set
ou defrozenset
, la recherche d'une IP de log dans l'ensemble est en O(1) — les set utilisent des tables de hachage comme les dict (redimensionnables pour limiter les collisions). Cf http://stackoverflow.com/questions/3949310/how-is-set-implementedVotez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Le type "set" ?
Posté par barmic . Évalué à 4.
Comment tu fais ça ?
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Le type "set" ?
Posté par lolop (site web personnel) . Évalué à 3.
Cf le lien que j'ai donné, quand ça collissionne, ils prennent une table plus large.
Et en plus il y a un genre de sel ajouté il y a quelques temps pour éviter les attaques via des requêtes web avec des chaines forgées qui donnaient des clés identiques.
+il y a le lien vers les sources si tu as du temps.
Mais, même en O(log(n)), ça serait plus rapide que du O(n/2) d'une recherche séquentielle.
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Le type "set" ?
Posté par lolop (site web personnel) . Évalué à 3.
Faudrait voir dans les détails comment ils se débrouillent (http://www.laurentluce.com/posts/python-dictionary-implementation/ => ils redimensionnent dès qu'une table de hachage est pleine aux deux tiers)… un petit test, en utilisant les dictionnaire installés:
Me donne:
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Le type "set" ?
Posté par barmic . Évalué à 4.
Donc dans "la recherche d'une IP de log dans l'ensemble est en O(1)", tu ignore la partie extraction des IP de ton log. C'est pourtant, à mon avis, ce qui est le plus couteux.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Le type "set" ?
Posté par lolop (site web personnel) . Évalué à 3.
Tu cherches quoi ? Tu as quelque chose à proposer sans avoir d'info sur la forme des lignes de logs?
Je n'ignore rien, l'extraction de l'IP du log peut être coûteuse, sa recherche en O(n) l'est au moins autant… sinon beaucoup plus s'il y a beaucoup d'adresses dans sa "grosse liste d'addresses IP". S'il a quelques milliers d'adresses IP dans sa liste, alors une recherche séquentielle est énormément plus coûteuse qu'une opération d'extraction.
Mais si Kwiknclean donne la forme de ses logs, il y aura probablement quelqu'un pour l'aider à écrire la regexp optimale qui va bien (peut-être pas moi sur les regexp).
J'ai modifié l'algo pour comparer la recherche en séquentielle (ie. dans la liste) à la recherche dans le set. Pour rappel, l'équivalent de la "gosse liste d'IPs" fait ~140000 entrées.
Et ça donne (temps en secondes):
Sans commentaire.
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Le type "set" ?
Posté par barmic . Évalué à 4.
Oui lis les autres commentaires…
Tu enfonce des portes ouvertes. Mais une autre possibilité pourrait être d'utiliser un tas pour ça. Si ces IPs recherchées sont rare dans les log (ce qui est potentiellement le cas), un bloom filter sera plus efficace encore. Mais ça reste très probablement de la microoptimisation parce que ce qui coute c'est l'extraction. Tu parle d'une recherche séquentielle sans résoudre le problème de l'extraction séquentielle.
C'est un peu comme si tu disais qu'il peut stocker les IP (v4) sous forme de 4 octets plutôt qu'en chaine de caractères qui peut faire 15 octets. Et montrer (benchmark à l'appuie) que pour 1000 ip : 1000*4 < 1000*15.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Le type "set" ?
Posté par lolop (site web personnel) . Évalué à 2.
Désespérant.
[]
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Le type "set" ?
Posté par lolop (site web personnel) . Évalué à 3. Dernière modification le 29 octobre 2014 à 15:22.
Correction, Regexp::Assemble est très intéressant. Juste vérifier qu'il n'y a pas de matchs incorrects (ie. connaître la forme/le type d'info dans les logs - qu'on ait pas plusieurs champs d'IP où il faut en ignorer certaines, sinon le pré-traitement fait perdre pas mal vis à vis de la solution).
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Le type "set" ?
Posté par Kwiknclean . Évalué à 2.
La liste d'IP n'est pas monstrueuse en fait ; une petite centaine, en forte croissance tous les mois toutefois.
En revanche le fichier lui fait un peu plus mal 1Go / jour en forte croissance, traitée tous les jours heureusement, c'est la log Nagios, la regex elle est triviale, l'Ip est toujours sur la deuxième ou troisième colonne, en fait un split suffit.
Question subsidiaire :
Dans mon exemple je boucle en premier sur les lignes de mon fichier.
Y aurait une différence notable si je commençais par boucler plutôt sur ma liste d'IP, ou ça n'a aucune incidence ?
[^] # Re: Le type "set" ?
Posté par lolop (site web personnel) . Évalué à 3.
Si tu utilises un set (ou frozenset), tu ne boucles plus sur la liste d'IPs. Il n'y a plus qu'une boucle sur ton fichier de log, le test de présence de l'IP de log dans ta collection est juste une opération ~simple~¹.
Il y a sûrement un équivalent en Perl au set Python, transforme ta liste d'IP dans cet outil, et déjà tu gagneras beaucoup sans trop toucher ton code.
…voir avec le Regexp::Assemble de M.Barrett - comme tu es déjà en Perl…
¹ En Python l'opérateur
in
appliqué à une liste fait comme toi, une boucle sur les éléments à la recherche de celui que tu testes. Par contre, l'opérateurin
appliqué à un set/frozenset c'est calcul de la clé de hachage si elle n'est pas déjà présente, mapping de celle-ci à l'index dans la table de répartition des clés, et identification (ou non) de la présence de ce que tu recherches (avec éventuellement parcours de qq valeurs s'il y a des collisions - cf un des autres commentaires et les liens accompagnant).Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
# En Python ?
Posté par feth . Évalué à 4. Dernière modification le 28 octobre 2014 à 23:34.
En Python. Je sais pas ce que je peux t'apprendre ou pas. Par contre ton énoncé est flou :)
Note : il y a au moins une bonne bibliothèque correcte pour gérer les adresses IP en Python :
# Regexp::Assemble
Posté par barmic . Évalué à 7.
Tout se perl ! Tu peut simplifier les choses avec Regexp::Assemble.
Tu dois pouvoir faire quelque chose comme ça :
Ce qui fait une complexité en O(n+m) avec n ip et m lignes.
Tu peut voir un bench là : http://articles.mongueurs.net/magazines/perles/perles-29.html
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Regexp::Assemble
Posté par Zylabon . Évalué à -4.
Il est rigolo ton lien :
« Lassé des problèmes sociaux causé par les inégalité, et constatant que nombre des richesses étaient accaparée par des gens d'origine juive (probablement parce qu'il faut bien être originaire de quelque chose), le parti nazi a pris des mesures radicales »
Please do not feed the trolls
[^] # Re: Regexp::Assemble
Posté par lolop (site web personnel) . Évalué à 4.
Trouvé un outil similaire à Regexp::Assemble en Python (ça peut toujours servir):
https://bitbucket.org/haypo/hachoir/wiki/hachoir-regex
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
# Merci les mecs !
Posté par Kwiknclean . Évalué à 4.
On fait du Python et du Perl dans la boite au choix (ils sont sympas ils nous laisse décider selon les périmètres).
Python j'trouve ça sympa mais ce manque de parenthèses et d'accolades ça me trouble, puis je fais très peu de POO.
Malgré tout Perl j'en démords pas même après toutes ces années, ces $, $_
je les adore.
D'ailleurs pourquoi on a plus de niouzes sur les nouvelles versions du langage sur linuxfr ?
Ca m'ennuie un peu d'utiliser un paquet CPAN quand même je voudrais proposer mon script à d'autre, mais ça m'a l'air rudement efficace.
Y a moyen d'ailleurs de "packager" des modules pour augmenter la portabilité ?
[^] # Re: Merci les mecs !
Posté par BAud (site web personnel) . Évalué à 5.
cela ne tient qu'à toi, cf. les appels récents à participation :
[^] # Re: Merci les mecs !
Posté par barmic . Évalué à 4. Dernière modification le 29 octobre 2014 à 09:08.
Tu peut faire de la détection de module, avoir un message d'alerte si le module n'est pas présent et utiliser comme moyen dégradé une combinaison de regexp à toi (un
join
avec "\|
" par exemple).Après il faut voir les volumes que tu as. Si tu as peu d'IP le module ne t'apportera pas de grosses optimisations.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
# En python ...
Posté par lolcat . Évalué à 3.
Si j'étais toi je ferai ça :
sortir toutes les ip de ton log, ce qui se fait très bien avec une expression régulière.
Puis regarder en python par exemple si ta liste d'IP match avec le module set.
Tu peux faire des opérations sur les ensembles facilement. D'ailleurs un des commentaires dit la même chose.
Si tu veux éviter les boucles, le mot clé in est pour toi. Il permet de vérifier qu'un élément appartient à une ligne sans la parser entièrement. après voir la librairie standard, tu as certainement plein de façons pour faire ce que tu veux.
[^] # Re: En python ...
Posté par barmic . Évalué à 5.
Ça me semble contre performant. Ça coute la construction de tes 2 ensemble plus l'intersection entre les deux, alors que tu peut filtrer déjà sur lors de la création de ton second ensemble (celui des ip du log). Oui les ensembles c'est très performants, mais c'est pas pour ça que c'est toujours pertinent (en l'occurrence je ne vois pas comment ça peut l'être).
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
# explication sur les sets
Posté par palm123 (site web personnel) . Évalué à 5.
http://sametmax.com/ce-que-vous-ne-saviez-pas-sur-les-collections-en-python/
http://sametmax.com/le-sourire-du-jour/
ウィズコロナ
[^] # Re: explication sur les sets
Posté par Kwiknclean . Évalué à 3.
Rien à voir mais : très sympa ta carte DDOS dans ta signature, on a cherché cet après midi avec un collègue à quoi pouvait correspondre géographiquement l'île qui semble bien active au Sud du pacifique face à l'Argentine …
Notre dernière hypothèse à la louche s'est arrêtée sur l'île de Bouvet … un caillou gelé de 40Km sans habitants … la NSA a mis un data-center dessus ou quoi ?
[^] # Re: explication sur les sets
Posté par palm123 (site web personnel) . Évalué à 3.
Je vais envoyer un email à la NSA, comme ça on saura
[]
comment on n'est pas dredi ?
ウィズコロナ
[^] # Re: explication sur les sets
Posté par palm123 (site web personnel) . Évalué à 2.
Je pense que plein de spammeurs prennent des .bv (pour Bouvet) et qu'il n'y a personne sur l'île, d'ailleurs la NSA ne m'a pas répondu.
ウィズコロナ
# Je ne pensais pas que ma question ...
Posté par Kwiknclean . Évalué à 4.
… déchainerait autant les passions.
Du calme les mecs ne vous emballez pas ;)
Et merci pour TOUTES vos propositions et manières de faire.
Pour situer un peu mieux le contexte, en fait il s'agit d'aller "filtrer" la log quotidienne Nagios qui pèse environ 1 Go ! en éliminant les lignes qui contiennent une liste d'IP donnée (une petite centaine je dirais), pour régénérer le fichier de log dépourvus des notifications de ces IP "parasites" avant traitement par un logiciel maison.
Enfin d'une manière général j'ai souvent ce type de "filtrage" à réaliser sur des log bien verboses, vsftp, squid, nagios ..
Donc oui les ensembles o(Ip * Nb Lignes) sont du genre très très gourmands …
[^] # Re: Je ne pensais pas que ma question ...
Posté par fearan . Évalué à 2.
en même temps
Forcément, les deux religions vont s'affronter; un peu comme une rencontre entre témoin de jéhovah et des jedi…
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
[^] # Re: Je ne pensais pas que ma question ...
Posté par Kwiknclean . Évalué à 1.
Ce n'était pas du tout volontaire du tout pourtant …
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.