Я могу использовать анализаторы журналов, но часто мне нужно проанализировать последние веб-журналы, чтобы увидеть, что происходит в данный момент.
Иногда я делаю такие вещи, как выяснение 10 лучших ips, которые запрашивают определенный файл
cat foo.log | grep request_to_file_foo | awk '{print $1}' | sort -n | uniq -c | sort -rn | head
Что у вас есть в вашем наборе инструментов?
Можно сделать в значительной степени что-либо с апачскими файлами журнала с одним только awk. Файлы журнала Apache являются в основном пробелом, разделенным, и можно притвориться, что кавычки не существуют, и доступ безотносительно информации, которой Вы интересуетесь номером столбца. Единственное время, которое это ломает, - то, если Вы имеете объединенный формат журнала и интересуетесь агентами пользователя, в которой точке необходимо использовать кавычки (") как разделитель и выполнить отдельную команду awk. Следующее покажет Вам дюйм/с каждого пользователя, который запрашивает индексную страницу, отсортированную по количеству хитов:
awk -F'[ "]+' '$7 == "/" { ipcount[$1]++ }
END { for (i in ipcount) {
printf "%15s - %d\n", i, ipcount[i] } }' logfile.log
7$ являются требуемым URL. Можно добавить любые условия, которые Вы хотите вначале. Замените '7$ == "/" с любой информацией, которую Вы хотите.
Если Вы заменяете 1$ в (ipcount [1$] ++), то можно сгруппировать результаты по другим критериям. Используя 7$ показал бы, к каким страницам получили доступ и как часто. Конечно, затем Вы хотели бы изменить условие вначале. Следующее показало бы, к каким страницам получил доступ пользователь от определенного IP:
awk -F'[ "]+' '$1 == "1.2.3.4" { pagecount[$7]++ }
END { for (i in pagecount) {
printf "%15s - %d\n", i, pagecount[i] } }' logfile.log
Можно также передать вывод по каналу через вид для приведения результатов в порядок, или как часть команды оболочки, или также в самом awk сценарии:
awk -F'[ "]+' '$7 == "/" { ipcount[$1]++ }
END { for (i in ipcount) {
printf "%15s - %d\n", i, ipcount[i] | sort } }' logfile.log
Последний был бы полезен, если бы Вы решили развернуть awk сценарий для распечатывания другой информации. Это - весь вопрос того, что Вы хотите узнать. Они должны служить начальной точкой для того, чем Вы интересуетесь.
поскольку IP рассчитывает в журнале доступа:
cat log | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" | sort -n | uniq -c | sort -n
Это немного ужасно, но это работает. Я также использую следующее с netstat (для наблюдения активных соединений):
netstat -an | awk '{print $5}' | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" | egrep -v "(`for i in \`ip addr | grep inet |grep eth0 | cut -d/ -f1 | awk '{print $2}'\`;do echo -n "$i|"| sed 's/\./\\\./g;';done`127\.|0\.0\.0)" | sort -n | uniq -c | sort -n
Они - часть моего фаворита "лайнеры" :)
Забудьте о awk и grep. Выезд asql. Почему запись нечитабельные сценарии, когда можно использовать sql как синтаксис для запросов файла журнала. Например.
asql v0.6 - type 'help' for help.
asql> load /home/skx/hg/engaging/logs/access.log
Loading: /home/skx/hg/engaging/logs/access.log
sasql> select COUNT(id) FROM logs
46
asql> alias hits SELECT COUNT(id) FROM logs
ALIAS hits SELECT COUNT(id) FROM logs
asql> alias ips SELECT DISTINCT(source) FROM logs;
ALIAS ips SELECT DISTINCT(source) FROM logs;
asql> hits
46
asql> alias
ALIAS hits SELECT COUNT(id) FROM logs
ALIAS ips SELECT DISTINCT(source) FROM logs;
Одна вещь, которую я никогда не видел, что кто-либо еще делает по причинам, что я не могу вообразить, состоит в том, чтобы изменить формат файла журнала Apache на более легко parseable версию с информацией, которая на самом деле имеет значение для Вас.
Например, мы никогда не используем HTTP основной автор, таким образом, мы не должны регистрировать те поля. Я интересуюсь тем, сколько времени каждый запрос берет для обслуживания, таким образом, мы включим это. Для одного проекта мы также хотим знать (на нашей подсистеме балансировки нагрузки), если какие-либо серверы служат запросам медленнее, чем другие, таким образом, мы регистрируем название сервера, мы проксируем назад к.
Вот выборка от апачской конфигурации одного сервера:
# We don't want to log bots, they're our friends
BrowserMatch Pingdom.com robot
# Custom log format, for testing
#
# date proto ipaddr status time req referer user-agent
LogFormat "%{%F %T}t %p %a %>s %D %r %{Referer}i %{User-agent}i" standard
CustomLog /var/log/apache2/access.log standard env=!robot
То, что Вы не можете действительно сказать от этого, - то, который между каждым полем литеральный символ табуляции (\t). Это означает, что, если я хочу сделать некоторый анализ в Python, возможно, покажите не200 состояний, например, я могу сделать это:
for line in file("access.log"):
line = line.split("\t")
if line[3] != "200":
print line
Или если я хотел сделать, 'кто изображения использования горячих ссылок?' это было бы
if line[6] in ("","-") and "/images" in line[5]:
Поскольку IP рассчитывает в журнале доступа, предыдущем примере:
grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" logfile | sort -n | uniq -c | sort -n
становится чем-то вроде этого:
cut -f 3 log | uniq -c | sort -n
Легче читать и понять, и намного менее в вычислительном отношении дорогой (никакой regex), который, на журналах на 9 ГБ, имеет огромное значение в том, сколько времени оно берет. То, когда это становится ДЕЙСТВИТЕЛЬНО аккуратным, - то, если Вы хотите сделать то же самое для Агентов пользователя. Если Ваши журналы разграничены пространством, необходимо сделать некоторое соответствие регулярного выражения или поиск строки вручную. С этим форматом это просто:
cut -f 8 log | uniq -c | sort -n
Точно то же как вышеупомянутое. На самом деле любая сводка, которую Вы хотите сделать, является по существу точно тем же.
С какой стати я потратил бы ЦП своей системы на awk и grep, когда сокращенный сделает точно, что я хочу порядки величины быстрее?
Создание списка общих вопросов было бы большим индексом для этого, отвечает на этот вопрос. Мои общие вопросы:
Я замечаю такие изменения путем контроля страниц состояния сервера (через mod_status) для hitrate и приблизительное время отклика для активных и недавно завершенных запросов (знающий очень хорошо, что я пропускаю огромную груду данных, но образцы достаточно хороши).
Я использую следующую директиву LogFormat (%T действительно полезен),
LogFormat "%h %l %u %t \"%r\" %>s %b
\"%{Referer}i\" \"%{User-Agent}i\" %T" custom
Я ищу причинно-следственный и что происходило сначала... обычно об определенных подмножествах шаблонов в моих журналах, таким образом, я должен знать следующее для любого данного шаблона/регулярного выражения:
Я обычно использую жемчуг, потому что в конечном счете это становится достаточно сложным для стоения.
non-perl примером была бы недоброкачественная продукция hitrate в минуту для не200 кодов состояния:
tail -9000 access_log | grep -v '" 200 ' | cut -d: -f2,3 | uniq -c
Да я обманываю с этим grep, предполагая, что quote-space-200-space соответствует только кодам состояния HTTP.... мог использовать awk, или жемчуг для изоляции поля просто имеют в виду, что это могло быть неточно.
Более сложный пример в жемчуге мог бы быть должен визуализировать изменение в hitrate для шаблона.
Существует много для жевания в сценарии ниже, особенно если Вы - unfamilar с жемчугом.
код следует:
#!/usr/bin/perl
# script to show changes in hitrates for any regex pattern
# results displayed with arbitrary intervals
# and ascii indication of frequency
# gaps are also displayed properly
use Date::Manip;
use POSIX qw(strftime);
$pattern=shift || ".";
$ival=shift || 60;
$tick=shift || 10;
$minb=undef;
while (<>){
next unless /$pattern/;
$stamp="$1 $2" if m[(../.../....):(..:..:..)];
$epoch = UnixDate(ParseDate($stamp),"%s");
$bucket= int($epoch/$ival)*$ival;
$minb=$bucket if $bucket<$minb || !defined($minb);
$maxb=$bucket if $bucket>$maxb;
$count{$bucket}++;
}
# loop thru the min/max range to expose any gaps
for($t=$minb;$t<=$maxb;$t+=$ival){
printf "%s %s %4d %s\n",
$t,
strftime("%m/%d/%Y %H:%M:%S",localtime($t)),
$count{$t}+0,
substr("x"x100,0,$count{$t}/$tick
);
}
Если Вы просто хотите обработать стандартные метрики, контроль
Здесь мой 'sed' пример, это читает формат по умолчанию апачских журналов и преобразовывает его во что-то более удобное для автоматической обработки. Целая строка определяется как регулярное выражение, переменные сохранены и записаны для вывода с '#' как разделитель.
Упрощенная нотация входа: %s %s %s [%s] "%s" %s %s "%s" "%s"
Пример ввел строку: xx.xx.xx.xx - [29/Mar/2011:12:33:02 +0200] "ПОЛУЧАЮТ /index.html HTTP/1.0" 200 9443 "-" "Mozilla/4.0"
Пример произвел строку: xx.xx.xx.xx#-#-#29/Mar/2011:12:33:02 +0200#GET /index.html HTTP/1.0#200#9443#-#Mozilla/4.0
cat access.log | \
sed 's/^\(.*\) \(.*\) \(.*\) \[\(.*\)\] \"\(.*\)\" \(.*\) \(.*\) \"\(.*\)\" \"\(.*\)\"$/\1#\2#\3#\4#\5#\6#\7#\8#\9/g'
Чувствуйте питание регулярных выражений :-)
Я часто использую awk, отслеживая или катая файл. Каждую ночь я отправляю себе веб-отчет для каждого сервера. В зависимости от вашего файла журнала и вашего LogFormat вам нужно будет отредактировать некоторые из этих лайнеров, чтобы они работали на вас ....
Вот простой пример:
Если я хочу отслеживать журналы на моем сервере всего за 404 Коды состояния / 500 Я бы сделал следующее:
# $6 is the status code in my log file
tail -f ${APACHE_LOG} | awk '$8 ~ /(404|500)/ {print $6}'
echo ""
#echo "Hits by source IP:"
echo "======================================================================"
awk '{print $2}' "$1" | grep -ivE "(127.0.0.1|192.168.100.)" | sort | uniq -c | sort -rn | head -25
echo ""
echo ""
#echo "The 25 most popular pages:"
echo "======================================================================"
awk '{print $6}' "$1" | grep -ivE '(mod_status|favico|crossdomain|alive.txt)' | grep -ivE '(.gif|.jpg|.png)' | \
sed 's/\/$//g' | sort | \
uniq -c | sort -rn | head -25
echo ""
echo ""
echo "The 25 most popular pages (no js or css):"
echo "======================================================================"
awk '{print $6}' "$1" | grep -ivE '(mod_status|favico|crossdomain|alive.txt)' | grep -ivE '(.gif|.jpg|.png|.js|.css)' | \
sed 's/\/$//g' | sort | \
uniq -c | sort -rn | head -25
echo ""
#echo "The 25 most common referrer URLs:"
echo "======================================================================"
awk '{print $11}' "$1" | \
grep -vE "(^"-"$|/www.$host|/$host)" | \
sort | uniq -c | sort -rn | head -25
echo ""
#echo "Longest running requests"
echo "======================================================================"
awk '{print $10,$6}' "$1" | grep -ivE '(.gif|.jpg|.png|.css|.js)' | awk '{secs=0.000001*$1;req=$2;printf("%.2f minutes req time for %s\n", secs / 60,req )}' | sort -rn | head -50
exit 0
snip>
Вот сценарий для поиска основных URL-адресов, основных источников перехода и основных пользователей из последних N записей журнала
#!/bin/bash
# Usage
# ls-httpd type count
# Eg:
# ls-httpd url 1000
# will find top URLs in the last 1000 access log entries
# ls-httpd ip 1000
# will find top IPs in the last 1000 access log entries
# ls-httpd agent 1000
# will find top user agents in the last 1000 access log entries
type=$1
length=$2
if [ "$3" == "" ]; then
log_file="/var/log/httpd/example.com-access_log"
else
log_file="$3"
fi
if [ "$type" = "ip" ]; then
tail -n $length $log_file | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" | sort -n | uniq -c | sort -n
elif [ "$type" = "agent" ]; then
tail -n $length $log_file | awk -F\" '{print $6}'| sort -n | uniq -c | sort -n
elif [ "$type" = "url" ]; then
tail -n $length $log_file | awk -F\" '{print $2}'| sort -n | uniq -c | sort -n
fi
Большую часть времени я обычно читаю разделы журнала по времени, поэтому я написал следующий сценарий, используя sed, чтобы выделить интересующий меня период, он работает с каждым файлом журнала, с которым я сталкивался, а также может обрабатывать архивные журналы.
#!/bin/bash #This script should return a set of lines between 2 values, the main purpose is for searching a log file between 2 times #Script usage: logship.sh "start" "stop" file #If the file contains any "/" in the date range the following 2 lines add the escape character so that the search can be performed for those characters start=$(echo "$1" | sed 's/\//\\\//g') stop=$(echo "$2" | sed 's/\//\\\//g') zipped=$(echo "$3" | grep -c "gz$") #figures out if the file is zipped or not if [ "$zipped" == "1" ]; then #If the file is zipped then pass it through zcat before sed zcat $3 | sed -n "/$start/,/$stop/p"; else sed -n "/$start/,/$stop/p" $3; #if it's not zipped just run sed fi
Хотя это и не sed или awk, есть две вещи, которые я нашел полезными для обработки файлов журналов apache и icecast.
AWStats имеет очень полезный сценарий под названием logresolvemerge. .pl , который объединяет несколько сжатых или несжатых файлов журнала, удаляет дубли и сортирует по отметкам времени. Он также может выполнять поиск DNS и быть настроен для работы в многопоточном режиме. Это особенно полезно при использовании с awstats, потому что awstats не может добавлять строки журнала с отметками времени старше, чем текущая база данных, поэтому все должны быть добавлены по порядку, но это очень просто, поскольку вы просто закидываете все в logresolvemerge.pl и это все появляется красиво.
sed и awk довольно плохо обрабатывают даты, потому что они обычно обрабатывают их как строки. В awk есть несколько функций времени и даты, но их не так много. Например, извлечь диапазон строк между двумя отметками времени сложно, если эти точные отметки времени не встречаются в файле (даже если значения между ними присутствуют) - пример Криса имеет именно эту проблему. Чтобы справиться с этим, я написал сценарий PHP , который сообщает диапазоны временных меток файла журнала, а также может извлекать фрагменты по диапазону меток времени, используя любой формат даты или времени, который вам нравится (он не должен соответствовать журналу формат временной метки файла).
Чтобы сохранить эту тему, вот несколько полезных awkisms: Получите общее количество обслуженных байтов из журнала apache или icecast:
cat access.log | awk '{ sum += $10 } END { print sum }'
Получите общее количество секунд, подключенных из журнала icecast:
cat access.log | awk '{ sum += $13 } END { print sum }'
При восстановлении этого старого потока, после отказа от asql для больших файлов журнала, снова искал решение, также в serverfault, я нашел о wtop здесь , это инструмент с открытым исходным кодом , который способен вести мониторинг в реальном времени или обрабатывать журналы и получать статистику (первые N), очень гибкий и мощный, официальное место - здесь