Выбрать главу

В случае с веб-серверами, которые не разбивают автоматически свои журналы на отдельные компоненты access_log и error_log, иногда есть возможность разделить централизованный журнал на эти составляющие, выполнив фильтрацию по коду результата (содержимому поля 8):

awk '{if (substr($9,0,1) <= "3") { print $0 } }' apache.log > access_log

awk '{if (substr($9,0,1) > "3") { print $0 } }' apache.log > error_log

Коды, начинающиеся с 4 или 5, сообщают об ошибке (коды 400–499 соответствуют ошибкам на стороне клиента, а коды 500–599 — на стороне сервера). Коды, начинающиеся с 2 или 3, сообщают об успешной обработке запроса (коды 200–299 соответствуют успешной обработке запросов, а коды 300–399 — успешной переадресации).

Другие серверы, поддерживающие единый файл журнала и фиксирующие в нем одновременно отчеты об успехе и об ошибках, снабжают записи с информацией об ошибках полем [error]. В этом случае с помощью команды grep '[error]' можно создать аналог журнала error_log, а с помощью команды grep −v '[error]' — аналог журнала access_log.

Независимо от того, создает ли ваш сервер журнал error_log автоматически или вы должны выделить его вручную, отыскав записи со строкой '[error]', структура записей в error_log практически всегда отличается от структуры записей в access_log, включая способ представления даты:

$ head -1 error_log

[Mon Jun 06 08:08:35 2016] [error] [client 54.204.131.75] File does not exist:

/var/www/vhosts/default/htdocs/clientaccesspolicy.xml

В access_log даты указываются в виде компактного значения, занимающего одно поле, без пробелов; в error_log дата занимает пять полей. Кроме того, в отличие от единообразной схемы access_log, в которой позиция поля со словом/строкой в записи четко определяется пробелами, записи в error_log включают содержательные описания ошибок, различающиеся по длине. Исследование одних только описаний показывает удивительное разнообразие, как демонстрируется ниже:

$ awk '{print $9" "$10" "$11" "$12 }' error_log | sort −u

File does not exist:

Invalid error redirection directive:

Premature end of script

execution failure for parameter

premature EOF in parsed

script not found or

malformed header from script

Некоторые из этих ошибок необходимо исследовать вручную, потому что определить причины их появления на странице порой бывает очень сложно.

Сценарий в листинге 10.5 решает только самые основные проблемы — в частности, отыскивает ошибки File does not exist («Файл не найден») — и просто выводит список всех остальных записей в error_log, которые не относятся к хорошо известным ситуациям.

Код

Листинг 10.5. Сценарий weberrors

··#!/bin/bash

··# weberrors — Сканирует файл error_log журнала сервера Apache, сообщает

··#·· о наиболее важных ошибках и выводит все остальные, неопознанные записи.

··temp="/tmp/$(basename $0).$$"

··# Для надежной работы этого сценария настройте следующие три переменные

··#·· в соответствии с вашей конфигурацией.

··htdocs="/usr/local/etc/httpd/htdocs/"

··myhome="/usr/home/taylor/"

··cgibin="/usr/local/etc/httpd/cgi-bin/"

··sedstr="s/^/ /g;s|$htdocs|[htdocs] |;s|$myhome|[homedir] "

··sedstr=$sedstr"|;s|$cgibin|[cgi-bin] |"

··screen="(File does not exist|Invalid error redirect|premature EOF"

··screen=$screen"|Premature end of script|script not found)"

··length=5 # Количество отображаемых записей в каждой категории

··checkfor()

··{

····grep "${2}:" "$1" | awk '{print $NF}' \

······| sort | uniq −c | sort −rn | head −$length | sed "$sedstr" > $temp

····if [$(wc −l < $temp) −gt 0]; then

······echo ""

······echo "$2 errors: "

······cat $temp

····fi

··}

··trap "$(which rm) −f $temp" 0

··if ["$1" = "-l"]; then

····length=$2; shift 2

··fi

··if [$# −ne 1 −o! −r "$1"]; then

····echo "Usage: $(basename $0) [-l len] error_log" >&2

····exit 1

··fi

··echo Input file $1 has $(wc −l < "$1") entries.

··start="$(grep −E '\[.*:.*:.*\]' "$1" | head -1 \

····| awk '{print $1" "$2" "$3" "$4" "$5 }')"

··end="$(grep −E '\[.*:.*:.*\]' "$1" | tail -1 \

····| awk '{print $1" "$2" "$3" "$4" "$5 }')"

··/bin/echo −n "Entries from $start to $end"

··echo ""

··### Проверить типичные и хорошо известные ошибки:

··checkfor "$1" "File does not exist"

··checkfor "$1" "Invalid error redirection directive"

··checkfor "$1" "Premature EOF"

··checkfor "$1" "Script not found or unable to stat"