web-dev-qa-db-fra.com

Filtrer les entrées du fichier journal en fonction de la plage de dates

Mon serveur a une utilisation CPU inhabituellement élevée, et je peux voir qu'Apache utilise beaucoup trop de mémoire. J'ai le sentiment que je suis sous DOS par une seule IP - peut-être pouvez-vous m'aider à le retrouver?

J'ai utilisé la ligne suivante pour trouver les 10 IP les plus "actives":

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

Les 5 meilleures adresses IP ont environ 200 fois plus de demandes au serveur que l'utilisateur "moyen". Cependant, je ne peux pas savoir si ces 5 sont des visiteurs très fréquents ou s'ils attaquent les serveurs.

Existe-t-il un moyen de spécifier la recherche ci-dessus à un intervalle de temps, par exemple. les deux dernières heures OR entre 10-12 aujourd'hui?

À votre santé!

MISE À JOUR 23 OCT 2011 - Les commandes dont j'avais besoin:

Obtenez des entrées au cours des X dernières heures [ici deux heures]

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

Obtenez les adresses IP les plus actives au cours des X dernières heures [ici deux heures]

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

Obtenez des entrées dans un délai relatif

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

Obtenez des entrées dans un délai absolu

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 

Obtenez les adresses IP les plus actives dans un délai absolu

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
35
sqren

oui, il existe plusieurs façons de procéder. Voici comment je procéderais à ce sujet. Pour commencer, pas besoin de diriger la sortie de cat, ouvrez simplement le fichier journal avec awk.

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

en supposant que votre journal ressemble au mien (ils sont configurables), la date est stockée dans le champ 4. et est entre crochets. Ce que je fais ci-dessus est de tout trouver au cours des 2 dernières heures. Note the -d'now-2 hours' ou traduit littéralement maintenant moins 2 heures, ce qui pour moi ressemble à ceci: [10/Oct/2011:08:55:23

Donc, ce que je fais, c'est de stocker la valeur formatée d'il y a deux heures et de comparer avec le champ quatre. L'expression conditionnelle doit être simple: j'imprime ensuite la date, suivie du séparateur de champ de sortie (OFS - ou espace dans ce cas) suivi de la ligne entière $ 0. Vous pouvez utiliser votre expression précédente et imprimer simplement $ 1 (les adresses 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 vous souhaitez utiliser une plage, spécifiez deux variables de date et construisez votre expression de manière appropriée.

donc si vous vouliez trouver quelque chose il y a entre 2 et 4 heures, votre expression pourrait ressembler à ceci

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'

Voici une question à laquelle j'ai répondu concernant les dates en bash qui pourraient vous être utiles. Imprimer la date du lundi de la semaine en cours (en bash)

38
matchew

Si quelqu'un rencontre le awk: invalid -v option, voici un script pour obtenir les IP les plus actives dans une plage de temps prédéfinie:

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
2
Szántó Zoltán

Comme il s'agit d'une tâche courantePerl

Et parce que ce n'est pas exactement la même chose que extraire les 10 dernières minutes du fichier journal où il s'agit d'un tas de temps jusqu'à la fin du fichier journal.

Et parce que j'en avais besoin, j'ai (rapidement) écrit ceci:

#!/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;
    };
};

Cela pourrait être utilisé comme:

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

pour l'impression des journaux entre 09h18 et 09h24.

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

pour l'impression à partir de january 23th, 9h18'12" jusqu'à maintenant.

Afin de réduire le code Perl, j'ai utilisé -s commutateur pour permettre l'attribution automatique de variables à partir de la ligne de commande: -s=09:18 remplira une variable $s qui contiendra 09:18. Attention à ne pas manquer le signe égal = et pas d'espaces!

Nota: Cela contient deux types différents de regex pour deux standards de log différents. Si vous avez besoin d'une analyse de format de date/heure différente, publiez votre propre expression régulière ou publiez un échantillon de date formatée à partir de votre fichier journal

^(\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]
2
F. Hauri