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
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)
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
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]