J'ai un fichier journal trié par adresses IP, je veux trouver le nombre d'occurrences de chaque adresse IP unique. Comment puis-je faire cela avec bash? Énumérant éventuellement le nombre d'occurrences à côté d'une adresse IP, comme:
5.135.134.16 count: 5
13.57.220.172: count 30
18.206.226 count:2
etc.
Voici un exemple du journal:
5.135.134.16 - - [23/Mar/2019:08:42:54 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
5.135.134.16 - - [23/Mar/2019:08:42:55 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
5.135.134.16 - - [23/Mar/2019:08:42:55 -0400] "POST /wp-login.php HTTP/1.1" 200 3836 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
5.135.134.16 - - [23/Mar/2019:08:42:55 -0400] "POST /wp-login.php HTTP/1.1" 200 3988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
5.135.134.16 - - [23/Mar/2019:08:42:56 -0400] "POST /xmlrpc.php HTTP/1.1" 200 413 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:05 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:06 -0400] "POST /wp-login.php HTTP/1.1" 200 3985 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:07 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:08 -0400] "POST /wp-login.php HTTP/1.1" 200 3833 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:09 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:11 -0400] "POST /wp-login.php HTTP/1.1" 200 3836 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:12 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:15 -0400] "POST /wp-login.php HTTP/1.1" 200 3837 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:17 -0400] "POST /xmlrpc.php HTTP/1.1" 200 413 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.233.99 - - [23/Mar/2019:04:17:45 -0400] "GET / HTTP/1.1" 200 25160 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"
18.206.226.75 - - [23/Mar/2019:21:58:07 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "https://www.google.com/url?3a622303df89920683e4421b2cf28977" "Mozilla/5.0 (Windows NT 6.2; rv:33.0) Gecko/20100101 Firefox/33.0"
18.206.226.75 - - [23/Mar/2019:21:58:07 -0400] "POST /wp-login.php HTTP/1.1" 200 3988 "https://www.google.com/url?3a622303df89920683e4421b2cf28977" "Mozilla/5.0 (Windows NT 6.2; rv:33.0) Gecko/20100101 Firefox/33.0"
18.213.10.181 - - [23/Mar/2019:14:45:42 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
18.213.10.181 - - [23/Mar/2019:14:45:42 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
18.213.10.181 - - [23/Mar/2019:14:45:42 -0400] "GET /wp-login.php HTTP/1.1" 200 2988 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
sort -V
mais je pense que ce n'était pas nécessaire. J'ai envoyé les 10 principaux abuseurs de la page de connexion à l'administrateur du système avec des recommandations pour interdire les sous-réseaux respectifs. par exemple, une adresse IP a atteint la page de connexion plus de 9 000 fois. cette IP et son sous-réseau de classe D sont désormais sur liste noire. Je suis sûr que nous pourrions automatiser cela, bien que ce soit une question différente.Réponses:
Vous pouvez utiliser
grep
etuniq
pour la liste des adresses, les parcourir en boucle etgrep
encore pour le décompte:grep -o '^[^ ]*'
renvoie chaque caractère du début (^
) jusqu'au premier espace de chaque ligne,uniq
supprime les lignes répétées, vous laissant ainsi une liste d'adresses IP. Grâce à la substitution de commande, lafor
boucle fait une boucle sur cette liste en imprimant l'IP en cours de traitement suivi de «count» et du count. Ce dernier est calculé pargrep -c
, qui compte le nombre de lignes avec au moins une correspondance.Exemple d'exécution
la source
uniq -c
ouawk
ne devant lire le fichier qu'une seule fois,<log grep ...
et nongrep ... log
?Vous pouvez utiliser
cut
etuniq
outils:Explication:
cut -d ' ' -f1
: extraire le premier champ (adresse IP)uniq -c
: signaler les lignes répétées et afficher le nombre d'occurrencesla source
sed
, par exemple,sed -E 's/ *(\S*) *(\S*)/\2 count: \1/'
pour obtenir la sortie exactement comme OP le voulait.sort file | cut ....
au cas où vous ne seriez pas sûr que le fichier est déjà trié.Si vous n'avez pas spécifiquement besoin du format de sortie donné, je recommanderais la réponse déjà publiée
cut
+uniq
baséeSi vous avez vraiment besoin du format de sortie donné, une façon de le faire en un seul passage dans Awk serait
Ceci n'est pas idéal lorsque l'entrée est déjà triée car elle stocke inutilement toutes les adresses IP en mémoire - une meilleure façon, bien que plus compliquée, de le faire dans le cas pré-trié (plus directement équivalent à
uniq -c
) serait:Ex.
la source
Voici une solution possible:
file.log
par le nom de fichier réel.$(awk '{print $1}' "$IN_FILE" | sort -u)
fournira une liste des valeurs uniques de la première colonne.grep -c
comptera chacune de ces valeurs dans le fichier.la source
printf
...Quelques Perl:
C'est la même idée que l'approche awk de Steeldriver , mais en Perl. Les
-a
Perl de diviser automatiquement chaque ligne d'entrée dans le réseau@F
, dont le premier élément (IP) est$F[0]
. Donc,$k{$F[0]}++
va créer le hachage%k
, dont les clés sont les IP et dont les valeurs sont le nombre de fois que chaque IP a été vue. Le}{
perlspeak est génial pour "faire le reste à la toute fin, après avoir traité toutes les entrées". Ainsi, à la fin, le script itérera sur les clés du hachage et affichera la clé actuelle ($_
) ainsi que sa valeur ($k{$_}
).Et, juste pour que les gens ne pensent pas que perl vous oblige à écrire un script qui ressemble à des gribouillages cryptiques, c'est la même chose sous une forme moins condensée:
la source
Ce n'est peut-être pas ce que souhaite le PO; cependant, si nous savons que la longueur de l'adresse IP sera limitée à 15 caractères, un moyen plus rapide d'afficher les décomptes avec des adresses IP uniques à partir d'un énorme fichier journal peut être obtenu en utilisant la
uniq
commande seule:Options:
-w N
ne compare pas plus deN
caractères que les lignes-c
préfixera les lignes par le nombre d'occurrencesAlternativement, pour une sortie formatée exacte, je préfère
awk
(devrait également fonctionner pour les adresses IPV6), ymmv.Notez que
uniq
ne détectera pas les lignes répétées dans le fichier d'entrée si elles ne sont pas adjacentes, il peut donc être nécessaire ausort
fichier.la source
FWIW, Python 3:
Production:
la source
Explication: prenez le premier champ de fractionnement my.log sur les tirets
-
et triez-le.uniq
nécessite une entrée triée.-c
lui dit de compter les occurrences.la source