Mi servidor está teniendo inusualmente elevado de CPU, y puedo ver que Apache está utilizando demasiada memoria.
Tengo una sensación, estoy siendo DOS había un solo IP – tal vez usted me puede ayudar a encontrarlo?

He utilizado la siguiente línea, para encontrar los 10 más «activo» IPs:

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

El top 5 de las IPs tienen alrededor de 200 veces el número de peticiones al servidor, como el «promedio» de usuario. Sin embargo, yo no puedo saber si estos 5 son muy frecuentes los visitantes, o están atacando los servidores.

Es que hay manera, para especificar la búsqueda anterior para un intervalo de tiempo, por ejemplo. las últimas dos horas O entre 10-12 hoy?

Saludos!

ACTUALIZADO el 23 de OCT de 2011 – Los comandos que yo necesitaba:

Obtener las entradas 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 Date FS $4}' access.log

Obtener más activos de IPs 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 $1}' access.log | sort  |uniq -c |sort -n | tail

Conseguir las entradas en relación timespan

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

Conseguir las entradas en absoluto timespan

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 

Obtener más activos de IPs dentro de absoluta timespan

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
  • Soy perezoso; me gustaría copia del registro en Excel y crear una tabla dinámica…
  • usted tiene dos problemas.»
InformationsquelleAutor sqren | 2011-10-09

3 Comentarios

  1. 38

    sí, hay varias maneras de hacer esto. He aquí cómo se podría ir sobre esto. Para empezar, no hay necesidad de canalizar la salida de gato, sólo tienes que abrir 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 a la mía (que son configurables) que a la fecha se almacena en el campo 4. y es que figura entre corchetes. Lo que yo estoy haciendo de arriba es la búsqueda de todo lo dentro de las últimas 2 horas. Note the -d'now-2 hours' o traducido literalmente, ahora menos 2 horas, que para mí se ve algo como esto: [10/Oct/2011:08:55:23

    Así que lo que estoy haciendo es almacenar el valor con formato de dos horas y comparar contra cuatro. La expresión condicional debe ser sencilla.Yo soy la impresión de la Fecha, seguido por la Salida del Separador de Campo (OFS-o espacio en este caso), seguido por el conjunto de la línea de $0. Usted puede utilizar su expresión anterior y sólo print $1 (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 queremos usar un rango de especificar la fecha de dos variables y la construcción de su expresión adecuada.

    así que si quería encontrar algo entre los 2-4 horas atrás su expresión se ve 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í es una pregunta que me respondió sobre las fechas en bash puede encontrar de utilidad.
    Fecha de impresión para el lunes de la semana actual (en bash)

    • Gracias hombre! Grandes ejemplos con buenas explicaciones. He elaborado el código para mis necesidades, y lo ha añadido a la pregunta original para referencia en el futuro para mí y para otros que lo necesitan.
    • me alegro de que podría ser de ayuda.
    • Una última cosa. ¿Cómo puedo buscar a través de múltiples archivos de registro? Estoy tratando de buscar y xargs pero no ha habido suerte: find-name ‘de acceso.registro’ | awk-vDate=date -d '13:20' +[%d/%b/%Y:%H:%M:%S -vDate2=date -d'13:40' +[%d/%b/%Y:%H:%M:%S ‘ { if ($4 > Fecha && $4 < Fecha2) print $1}’ xargs | sort |uniq -c |sort-n | cola
    • día ajetreado, así que le voy a dar una respuesta detallada después del trabajo. Si usted no necesita conservar para el nombre del documento que usted podría utilizar un pegote como access_logs.2011-* los que se encuentran todos los registros de 2011, asumiendo su aspecto parecen access_log.YYYY-MM, si usted necesita para mantener los nombres trate de usar un bucle for.
    • Es awk de alguna manera lo suficientemente inteligente para adivinar que estás comparando fechas ? Porque yo diría que es justo comparar cadenas, y desde fechas no ordenar la misma como cadenas de caracteres (por defecto en la nginx formato que usted esté usando)… así que hice algunas pruebas rápidas y me da menos resultados para el último mes de la pasada jornada, por lo que lo hace parecer una especie de rota
    • Originalmente me respondió esta pregunta en 2011. Estaba buscando en archivos de registro de apache no nginx. Yo estoy familiarizado con nginx. ¿Usa el mismo formato por defecto de apache?
    • Lo siento resurgir esto, pero estoy bastante seguro de que mi punto no depende de la versión de awk, y, de hecho, nginx en 2018 parece estar usando el mismo formato de fecha como de apache en 2011. La pregunta es cómo lidiar con el hecho de que [01/Feb/20XX < [02/Feb/20XX < [31/Jan/20XX ?
    • Sí, aquí mismo! Me enfrenté con esta demasiado [27/May/2018:03:12:01 > [01/Jun/2018:09:14:26
    • Sí, se trata de un simple comparación en cadena de la fecha de dos cadenas de caracteres que puede fallar si las dos fechas en los diferentes meses del año. Intentar algo como esto: awk -F'[][]' -v dstart=`date -d"-2 hours" +%Y%m%dT%0H:%0M:%0S` '{ $2 = substr($2,8,4)sprintf("%02d",(match("JanFebMarAprMayJunJulAugSepOctNovDec",substr($2,4,3))+2)/3)substr($2,1,2)"T"substr($2,13,8); if ($2 > dstart) print }' access_log

  2. 2

    Como este es un común tarea

    Y debido a que esta no es exactamente la misma que la extracto ú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 lo he necesitado, me (rápidamente) escribió esto:

    #!/usr/bin/perl -ws
    # This script parse logfiles for a specific period of time
    
    sub usage {
        printf "Usage: %s -s=<start time> [-e=<end time>] <logfile>\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 ser utilizado como:

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

    para la impresión de registros entre las 09h18 y 09h24.

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

    para la impresión de january 23th, 9h18'12" hasta ahora.

    Con el fin de reducir el código perl, he usado -s interruptor para permitir la auto-asignacion de variables de línea de comandos: -s=09:18 rellenará una variable $s que contienen 09:18. Cuidado para que no se pierda el signo igual = y sin espacios!

    Nota: Esta dos diferentes tipo de regex por dos tipos de registro estándar. Si usted requiere de diferente formato de fecha/hora de analizar, publicar su propio regex o publicar una muestra de formato de la fecha 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]
    • Muy agradable respuesta, he añadido esto a un bucle, y que fácilmente se puede investigar lo que sucedió en un servidor.
  3. 2

    Si alguien se encuentra con la awk: invalid -v option, he aquí una secuencia de comandos para obtener el mayor activo de IPs en un intervalo de tiempo predefinido:

    cat <FILE_NAME> | 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
    • El cat es (todavía) un inútil.
    • De nuevo esto puede fallar si las fechas están en los diferentes meses del año (por ejemplo, «Mayo»>»Jun»). Ver mi comentario de arriba por un camino para convertir la cadena de caracteres para el número. Brevemente, monthnum=match("JanFebMarAprMayJunJulAugSepOctNovDec",monthstr)+2)/3

Dejar respuesta

Please enter your comment!
Please enter your name here