Filtrar las entradas del archivo de registro según el rango de fechas

Mi servidor tiene un uso de CPU inusualmente alto, y puedo ver que Apache usa demasiada memoria. Tengo la sensación, estoy siendo sometido a DOS por una única IP. ¿Quizás puedas ayudarme a encontrarlo?

He usado la siguiente línea para encontrar las 10 IP más “activas”:

cat access.log | awk '{print $1}' |sort |uniq -c |sort -n |tail 

Las 5 principales IP tienen aproximadamente 200 veces más solicitudes al servidor, que el usuario “promedio”. Sin embargo, no puedo averiguar si estos 5 son solo visitantes frecuentes o están atacando a los servidores.

¿Hay alguna manera de especificar la búsqueda anterior a un intervalo de tiempo, por ej. las últimas dos horas O entre 10-12 hoy?

¡Aclamaciones!

ACTUALIZADO EL 23 DE OCTUBRE DE 2011 – Los comandos que necesitaba:

Obtener entradas dentro de las últimas X horas [Aquí dos horas]

 awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date) print Date FS $4}' access.log 

Obtenga las direcciones IP más activas en las últimas X horas [Aquí dos horas]

 awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date) print $1}' access.log | sort |uniq -c |sort -n | tail 

Obtener entradas dentro de un lapso de tiempo relativo

 awk -vDate=`date -d'now-4 hours' +[%d/%b/%Y:%H:%M:%S` -vDate2=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date && $4 < Date2) print Date FS Date2 FS $4}' access.log 

Obtener entradas dentro de un lapso de tiempo absoluto

 awk -vDate=`date -d '13:20' +[%d/%b/%Y:%H:%M:%S` -vDate2=`date -d'13:30' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date && $4 < Date2) print $0}' access.log 

Obtenga las direcciones IP más activas dentro de un intervalo de tiempo absoluto

 awk -vDate=`date -d '13:20' +[%d/%b/%Y:%H:%M:%S` -vDate2=`date -d'13:30' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date && $4 < Date2) print $1}' access.log | sort |uniq -c |sort -n | tail 

sí, hay múltiples formas de hacer esto. Así es como voy a hacer esto. Para empezar, no hay necesidad de canalizar la salida de cat, solo abre el archivo de registro con awk .

 awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` '$4 > Date {print Date, $0}' access_log 

asumiendo que su registro se parece al mío (son configurables) que la fecha se almacena en el campo 4. y está entre corchetes. Lo que estoy haciendo arriba es encontrar todo en las últimas 2 horas. Note the -d'now-2 hours' o traducido literalmente ahora menos 2 horas, que para mí se ve así: [10/Oct/2011:08:55:23

Entonces, lo que estoy haciendo es almacenar el valor formateado de hace dos horas y compararlo con el campo cuatro. La expresión condicional debe ser directa. Entonces estoy imprimiendo la Fecha, seguido del Separador de Campo de Salida (OFS – o espacio en este caso) seguido de toda la línea $ 0. Podría usar su expresión anterior e imprimir solo $ 1 (las direcciones IP)

 awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` '$4 > Date {print $1}' | sort |uniq -c |sort -n | tail 

Si desea usar un rango, especifique dos variables de fecha y construya su expresión de manera apropiada.

así que si quisieras encontrar algo entre 2 a 4 horas atrás, tu expresión podría ser algo como esto

 awk -vDate=`date -d'now-4 hours' +[%d/%b/%Y:%H:%M:%S` -vDate2=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` '$4 > Date && $4 < Date2 {print Date, Date2, $4} access_log' 

Aquí hay una pregunta que respondí con respecto a las fechas en bash que pueden ser útiles. Imprimir fecha para el lunes de la semana actual (en bash)

Si alguien encuentra la awk: invalid -v option , aquí hay una secuencia de comandos para obtener las IP más activas en un rango de tiempo predefinido:

 cat  | awk '$4 >= "[04/Jul/2017:07:00:00" && $4 < "[04/Jul/2017:08:00:00"' | awk '{print $1}' | sort -n | uniq -c | sort -nr | head -20 

Como esta es una tarea perl común

Y porque esto no es exactamente lo mismo que extraer los últimos 10 minutos del archivo de registro, donde se trata de un montón de tiempo hasta el final del archivo de registro.

Y porque los he necesitado, (rápidamente) escribí esto:

 #!/usr/bin/perl -ws # This script parse logfiles for a specific period of time sub usage { printf "Usage: %s -s= [-e=] \n"; die $_[0] if $_[0]; exit 0; } use Date::Parse; usage "No start time submited" unless $s; my $startim=str2time($s) or die; my $endtim=str2time($e) if $e; $endtim=time() unless $e; usage "Logfile not submited" unless $ARGV[0]; open my $in, "<" . $ARGV[0] or usage "Can't open '$ARGV[0]' for reading"; $_=<$in>; exit unless $_; # empty file # Determining regular expression, depending on log format my $logre=qr{^(\S{3}\s+\d{1,2}\s+(\d{2}:){2}\d+)}; $logre=qr{^[^\[]*\[(\d+/\S+/(\d+:){3}\d+\s\+\d+)\]} unless /$logre/; while (<$in>) { /$logre/ && do { my $ltim=str2time($1); print if $endtim >= $ltim && $ltim >= $startim; }; }; 

Esto podría usarse como:

 ./timelapsinlog.pl -s=09:18 -e=09:24 /path/to/logfile 

para imprimir registros entre las 09h18 y las 09h24.

 ./timelapsinlog.pl -s='2017/01/23 09:18:12' /path/to/logfile 

para imprimir desde el january 23th, 9h18'12" hasta ahora .

Para reducir el código perl, he usado -s para habilitar la asignación automática de variables desde la línea de comandos: -s=09:18 llenará una variable $s que contendrá 09:18 . ¡Cuidado para no perder el signo igual = y sin espacios!

Nota: Esto contiene dos tipos de expresiones regulares diferentes para dos estándares de registro diferentes. Si necesita un análisis de formato de fecha / hora diferente, publique su propia expresión regular o publique una muestra de la fecha formateada de su archivo de registro.

 ^(\S{3}\s+\d{1,2}\s+(\d{2}:){2}\d+) # ^Jan 1 01:23:45 ^[^\[]*\[(\d+/\S+/(\d+:){3}\d+\s\+\d+)\] # ^... [01/Jan/2017:01:23:45 +0000]