Ich habe eine Protokolldatei, die nach IP-Adressen sortiert ist. Ich möchte die Anzahl der Vorkommen jeder eindeutigen IP-Adresse ermitteln. Wie kann ich das mit bash machen? Möglicherweise wird die Anzahl der Vorkommen neben einer IP-Adresse aufgeführt, z. B .:
5.135.134.16 count: 5
13.57.220.172: count 30
18.206.226 count:2
und so weiter.
Hier ist ein Beispiel des Protokolls:
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"
command-line
bash
sort
uniq
j0h
quelle
quelle
sort -V
obwohl ich denke, dass dies nicht erforderlich war. Ich habe die 10 häufigsten Nutzer der Anmeldeseite mit Empfehlungen zum Sperren der jeweiligen Subnetze an den Systemadministrator gesendet. Beispielsweise hat eine IP die Anmeldeseite mehr als 9000 Mal aufgerufen. Diese IP und ihr Subnetz der Klasse D sind jetzt auf der schwarzen Liste. Ich bin sicher, wir könnten das automatisieren, obwohl das eine andere Frage ist.Antworten:
Sie können
grep
unduniq
für die Liste der Adressen verwenden und diese immergrep
wieder für die Zählung durchlaufen:grep -o '^[^ ]*'
Gibt jedes Zeichen von Anfang an (^
) bis zum ersten Leerzeichen jeder Zeile aus,uniq
entfernt wiederholte Zeilen und hinterlässt so eine Liste mit IP-Adressen. Dank der Befehlssubstitution durchläuft diefor
Schleife diese Liste und druckt die aktuell verarbeitete IP, gefolgt von „count“ und der Anzahl. Letzteres wird mit berechnetgrep -c
, wobei die Anzahl der Zeilen mit mindestens einer Übereinstimmung gezählt wird.Beispiellauf
quelle
uniq -c
oderawk
müssen die Datei nur einmal lesen,<log grep ...
und nicht sogrep ... log
?Sie können
cut
unduniq
Werkzeuge verwenden:Erklärung:
cut -d ' ' -f1
: Erstes Feld extrahieren (IP-Adresse)uniq -c
: Wiederholte Zeilen melden und Anzahl der Vorkommen anzeigenquelle
sed
zB verwendensed -E 's/ *(\S*) *(\S*)/\2 count: \1/'
, um die Ausgabe genau so zu bekommen, wie OP es wollte.sort file | cut ....
, wenn Sie nicht sicher sind, ob die Datei bereits sortiert ist.Wenn Sie das angegebene Ausgabeformat nicht speziell benötigen, würde ich die bereits gepostete + Antwort empfehlen
cut
uniq
Wenn Sie das angegebene Ausgabeformat wirklich benötigen, ist dies in Awk in einem Durchgang möglich
Dies ist nicht ideal, wenn die Eingabe bereits sortiert ist, da unnötigerweise alle IP-Adressen im Speicher gespeichert werden - eine bessere, wenn auch kompliziertere Möglichkeit, dies im vorsortierten Fall zu tun (direkter äquivalent zu
uniq -c
), wäre:Ex.
quelle
Hier ist eine mögliche Lösung:
file.log
mit dem tatsächlichen Dateinamen.$(awk '{print $1}' "$IN_FILE" | sort -u)
liefert eine Liste der eindeutigen Werte der ersten Spalte.grep -c
wird jeder dieser Werte in der Datei gezählt.quelle
printf
...Einige Perl:
Dies ist die gleiche Idee wie Steeldrivers awk-Ansatz , jedoch in Perl. Das
-a
bewirkt, dass Perl jede Eingabezeile automatisch in das Array aufteilt@F
, dessen erstes Element (die IP) ist$F[0]
. Also$k{$F[0]}++
wird der Hash erstellt%k
, dessen Schlüssel die IPs sind und dessen Werte die Häufigkeit sind, mit der jede IP gesehen wurde. Das}{
ist funky perlspeak für "Mach den Rest am Ende, nachdem du alle Eingaben verarbeitet hast". Am Ende durchläuft das Skript die Schlüssel des Hashs und gibt den aktuellen Schlüssel ($_
) zusammen mit seinem Wert ($k{$_}
) aus.Und nur damit die Leute nicht glauben, dass Perl Sie zwingt, ein Skript zu schreiben, das wie kryptische Kritzeleien aussieht, ist dies in einer weniger komprimierten Form dasselbe:
quelle
Vielleicht ist es nicht das, was die OP wollen; Wenn wir jedoch wissen, dass die Länge der IP-Adresse auf 15 Zeichen begrenzt ist, können Sie die Anzahl der eindeutigen IP-Adressen aus einer großen Protokolldatei schneller anzeigen, indem Sie den
uniq
Befehl allein verwenden:Optionen:
-w N
vergleicht nicht mehr alsN
Zeichen in Zeilen-c
wird den Zeilen die Anzahl der Vorkommen voranstellenAlternativ bevorzuge ich für eine exakt formatierte Ausgabe
awk
(sollte auch für IPV6-Adressen funktionieren) ymmv.Beachten Sie, dass
uniq
wiederholte Zeilen in der Eingabedatei nicht erkannt werden, wenn sie nicht benachbart sind. Daher kann dies fürsort
die Datei erforderlich sein .quelle
FWIW, Python 3:
Ausgabe:
quelle
Erläuterung: Nehmen Sie das erste Feld von my.log, das in Bindestriche aufgeteilt ist,
-
und sortieren Sie es.uniq
benötigt sortierte Eingabe.-c
sagt, es soll Vorkommen zählen.quelle