Mam plik dziennika posortowany według adresów IP, chcę znaleźć liczbę wystąpień każdego unikalnego adresu IP. Jak mogę to zrobić za pomocą bash? Prawdopodobnie podaje liczbę wystąpień obok adresu IP, takie jak:
5.135.134.16 count: 5
13.57.220.172: count 30
18.206.226 count:2
i tak dalej.
Oto próbka dziennika:
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
źródło
źródło
sort -V
choć myślę, że nie było to wymagane. Wysłałem 10 najlepszych osób nadużywających strony logowania do administratora systemu z zaleceniami dotyczącymi banowania odpowiednich podsieci. na przykład One IP trafił na stronę logowania ponad 9000 razy. ten adres IP i jego podsieć klasy D są teraz na czarnej liście. Jestem pewien, że możemy to zautomatyzować, ale to inne pytanie.Odpowiedzi:
Możesz użyć
grep
iuniq
do listy adresów, zapętlić je igrep
ponownie dla liczby:grep -o '^[^ ]*'
wypisuje każdy znak od początku (^
) do pierwszej spacji każdego wiersza,uniq
usuwa powtarzające się wiersze, pozostawiając w ten sposób listę adresów IP. Dzięki podstawieniu poleceńfor
pętla zapętla tę listę, drukując aktualnie przetwarzany adres IP, a następnie „count” i count. Ten ostatni jest obliczany przezgrep -c
, który zlicza liczbę linii z co najmniej jednym dopasowaniem.Przykładowy przebieg
źródło
uniq -c
lubawk
czytające go tylko raz,<log grep ...
i niegrep ... log
?Możesz użyć
cut
iuniq
narzędzi:Objaśnienie:
cut -d ' ' -f1
: wyodrębnij pierwsze pole (adres IP)uniq -c
: zgłoś powtarzające się wiersze i wyświetl liczbę wystąpieńźródło
sed
np.,sed -E 's/ *(\S*) *(\S*)/\2 count: \1/'
Aby uzyskać wynik dokładnie taki, jaki chciał OP.sort file | cut ....
jeśli nie masz pewności, czy plik jest już posortowany.Jeśli nie potrzebujesz konkretnego formatu wyjściowego, polecam już wysłaną odpowiedź opartą na
cut
+uniq
Jeśli naprawdę potrzebujesz podanego formatu wyjściowego, możesz to zrobić w Awk za pomocą jednego przejścia
Jest to nieco nieidealne, gdy dane wejściowe są już posortowane, ponieważ niepotrzebnie przechowuje wszystkie adresy IP w pamięci - lepszym, choć bardziej skomplikowanym, sposobem na zrobienie tego w przypadku wstępnie posortowanego (bardziej bezpośrednio równoważnego
uniq -c
) byłoby:Dawny.
źródło
Oto jedno z możliwych rozwiązań:
file.log
rzeczywistą nazwą pliku.$(awk '{print $1}' "$IN_FILE" | sort -u)
zapewni listę unikatowych wartości pierwszej kolumny.grep -c
policzy każdą z tych wartości w pliku.źródło
printf
...Some Perl:
To ten sam pomysł, co podejście awk Steeldrivera , ale w Perlu. Do
-a
przyczyn Perl automatycznie podzielić każdą linię wejścia do tablicy@F
, której pierwszy element (IP) to$F[0]
. Utworzy więc$k{$F[0]}++
skrót%k
, którego kluczami są adresy IP, a których wartości to liczba wyświetleń każdego adresu IP. Jest}{
to funky perlspeak dla „wykonaj resztę na samym końcu, po przetworzeniu wszystkich danych wejściowych”. Na koniec skrypt będzie iterował klucze skrótu i wypisał bieżący klucz ($_
) wraz z jego wartością ($k{$_}
).I tak, żeby ludzie nie myśleli, że Perl zmusza cię do napisania skryptu, który wygląda jak tajemnicze bazgroły, jest to to samo w mniej skondensowanej formie:
źródło
Może nie tego chce OP; Jeśli jednak wiemy, że długość adresu IP będzie ograniczona do 15 znaków, szybszy sposób wyświetlania liczby unikatowych adresów IP z dużego pliku dziennika można uzyskać za pomocą
uniq
samej komendy:Opcje:
-w N
porównuje nie więcej niżN
znaki w wierszach-c
będzie poprzedzać wiersze liczbą wystąpieńAlternatywnie, dla dokładnego sformatowania danych wyjściowych wolę
awk
(powinien również działać dla adresów IPV6), ymmv.Zauważ, że
uniq
nie wykryje powtarzających się linii w pliku wejściowym, jeśli nie są one sąsiadujące, więc może być konieczne dosort
pliku.źródło
FWIW, Python 3:
Wynik:
źródło
Objaśnienie: Weź pierwsze pole podziału my.log na myślniki
-
i posortuj je.uniq
wymaga posortowanego wejścia.-c
każe policzyć zdarzenia.źródło