Tengo un archivo de registro ordenado por direcciones IP, quiero encontrar el número de ocurrencias de cada dirección IP única. ¿Cómo puedo hacer esto con bash? Posiblemente enumere el número de ocurrencias junto a una ip, como:
5.135.134.16 count: 5
13.57.220.172: count 30
18.206.226 count:2
y así.
Aquí hay una muestra del registro:
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
fuente
fuente
sort -V
aunque creo que no fue necesario. Envié los 10 principales abusadores de la página de inicio de sesión al administrador del sistema con recomendaciones para prohibir las subredes respectivas. por ejemplo, una IP golpeó la página de inicio de sesión más de 9000 veces. esa IP, y su subred de clase D ahora está en la lista negra. Estoy seguro de que podríamos automatizar esto, aunque esa es una pregunta diferente.Respuestas:
Puede usar
grep
yuniq
para la lista de direcciones, recorrerlas ygrep
nuevamente para el recuento:grep -o '^[^ ]*'
genera cada carácter desde el principio (^
) hasta el primer espacio de cada línea,uniq
elimina las líneas repetidas y le deja una lista de direcciones IP. Gracias a la sustitución de comandos, elfor
bucle recorre esta lista imprimiendo la IP procesada actualmente seguida de "conteo" y el conteo. Este último se calcula porgrep -c
, que cuenta el número de líneas con al menos una coincidencia.Ejecución de ejemplo
fuente
uniq -c
oawk
solo necesitan leer el archivo una vez,<log grep ...
y nogrep ... log
?Puedes usar
cut
yuniq
herramientas:Explicacion:
cut -d ' ' -f1
: extraer el primer campo (dirección IP)uniq -c
: informa líneas repetidas y muestra el número de ocurrenciasfuente
sed
, por ejemplo,sed -E 's/ *(\S*) *(\S*)/\2 count: \1/'
para obtener la salida exactamente como OP quería.sort file | cut ....
en caso de que no esté seguro de si el archivo ya está ordenado.Si no requiere específicamente el formato de salida dado, recomendaría la respuesta basada en + ya publicada
cut
uniq
Si realmente necesita el formato de salida dado, una forma de paso único para hacerlo en Awk sería
Esto es algo no ideal cuando la entrada ya está ordenada, ya que almacena innecesariamente todas las IP en la memoria; una forma mejor, aunque más complicada, de hacerlo en el caso previamente ordenado (más directamente equivalente a
uniq -c
) sería:Ex.
fuente
Aquí hay una posible solución:
file.log
con el nombre real del archivo.$(awk '{print $1}' "$IN_FILE" | sort -u)
proporcionará una lista de los valores únicos de la primera columna.grep -c
contará cada uno de estos valores dentro del archivo.fuente
printf
...Algunos Perl:
Esta es la misma idea que el enfoque awk de Steeldriver , pero en Perl. Las
-a
causas perl para dividir automáticamente cada línea de entrada en la matriz@F
, cuyo primer elemento (la IP) es$F[0]
. Entonces,$k{$F[0]}++
creará el hash%k
, cuyas claves son las IP y cuyos valores son la cantidad de veces que se vio cada IP. El}{
es funky perlspeak para "hacer el resto al final, después de procesar todas las entradas". Entonces, al final, el script iterará sobre las claves del hash e imprimirá la clave actual ($_
) junto con su valor ($k{$_}
).Y, para que la gente no piense que Perl te obliga a escribir guiones que parecen garabatos crípticos, esto es lo mismo en una forma menos condensada:
fuente
Quizás esto no sea lo que quiere el OP; sin embargo, si sabemos que la longitud de la dirección IP se limitará a 15 caracteres, se puede lograr una forma más rápida de mostrar los recuentos con direcciones IP únicas de un archivo de registro enorme utilizando
uniq
solo el comando:Opciones:
-w N
no compara más queN
caracteres en líneas-c
prefijará líneas por el número de ocurrenciasAlternativamente, para la salida con formato exacto que prefiero
awk
(también debería funcionar para direcciones IPV6), ymmv.Tenga en cuenta que
uniq
no detectará líneas repetidas en el archivo de entrada si no son adyacentes, por lo que puede ser necesario parasort
el archivo.fuente
FWIW, Python 3:
Salida:
fuente
Explicación: Tome el primer campo de división my.log en guiones
-
y ordénelo .uniq
necesita entrada ordenada.-c
le dice que cuente las ocurrencias.fuente