Home > life > Определение проблем Apache

Определение проблем Apache

Перевод статьи Debugging Apache web server problems. Ох и сложно она мне далась! Переводил очень долго, много переписывал, но таки очень коряво получилось. Да и материальчик сложноват и терминов много.

Обзор

Web-сервер Apache стал доминирующим web-серверром в интернет благодаря своей расширяемости, поддержке стандартов и многочисленным особенностям, входящим в сервер. Поскольку все больше и больше функций добавляется в Apache, а также веб-приложения развиваются с учетом новых требований, ошибки периодически выплывают в коде приложений и самого web-сервера. Поскольку ошибки приложений и Apache могут привести к отказам в работе и простою, важно иметь хороший набор инструментов для помощи в выявлении и устранении проблем. В этой статье предоставлено введение к отладке проблем web-сервера Apache и охватывает ряд инструментов и методов, которые могут помочь устранить возникающие неполадки.

Изоляция проблем Apache в одно-процессном режиме

Когда отлаживаются проблемы web-сервера, изоляция проблемы – первый шаг к устранении неполадок. Поскольку при установке по-умолчанию apache запускается с несколькими процессами как worker или event MPMs multiple threads per process (перевод строки “and in the case of the worker and event MPMs multiple threads per process” не сложился ;) Поможете? ), запуск Apache в режиме одного процесса может упростить устранение ошибки. Есть 2 пути это сделать. Первый – это отредактировать количество процессов и потоков в настройке MPM. Альтернативным методом является запуск apache с опцией “-X”, который заставит запустится сервер в одно-процессорном режиме:


$ httpd -X

Когда используется одно-процессорный режим, Apache не создаёт новые процессы и не выходит с терминал. Это гарантирует, что все соединения проходят через один поток, который разрешает процедуры устранение ошибок (например, присоединение процесса httpd к gdb) , которые будут использованы в одном потоке вместо многих.

Отладка проблем в конфигурационном файле

С течением времени для некоторых веб-сайтов, файл конфигурации Apache может вырасти в довольно сложный файл. Когда возникают ошибки в конфигурации, возможность быстро локализовать источник ошибки может сократить время устранения неполадок. Apache имеет два метода для устранения проблем с конфигурированием. Первый способ – опция httpd “-t” , которая может быть использована для проверки файла настройки на синтаксические ошибки:


$ httpd -t -c httpd.conf
Syntax error on line 236 of /etc/httpd/httpd.conf:
LogLevel requires level keyword: one of emerg/alert/crit/error/warn/notice/info/debug

Если есть ошибка, то выведется строка с ошибкой и описание возможных опций, если их удалось определить. Если apache не запускается и анализатор синтаксиса говорит, что с конфигурационным файлом всё нормально, можно использовать apache debug log level, чтобы получить дополнительные данные в error_log.

Чтобы включить debug log level нужно в директиве “LogLevel” файла настройки Apache указать параметр “debug”.

Отладка проблем выполнения скриптов

Модуль Apache mod_cgi позволяет скриптам выполнятся в период запроса. CGI скрипт может быть написан на одном с многочисленных скриптовых языков и позволяет динамически создавать контент для клиентов. Когда возникает ошибка в скрипте, который выполняется mod_cgi, определение почему этот сценарий не удалось запустить, может вызвать множество проблем.

Один способ отловить ошибку – это директива mod_cgi “ScriptLog”. Когда ScriptLog включён, mod_cgi пишет в лог-файл весь вывод с каждого CGI-скрипта, который не выполнился правильно. В этом выводе: ответ сервера, запрос, который был отправлен, ответ, отправленый клиенту (если вообсче был отправлен) и это прекрассный инструмент для отладки, когда ошибки скриптавалятся в error_log или когда пользователь жалуется, что что-то не работает правильно.

Включить логирование ошибок CGI-скриптов в файле конфигурации Apache можно с помощью директивы “ScriptLog”, как и файл для логов. Когда ScriptLog включеный, mod_cgi записывает в лог-файл данные такого виду каждый раз, когда неправильно выполняется скрипт:


%% [Tue Dec 26 14:47:21 2006] GET /cgi-bin/print HTTP/1.1
%% 500 /var/tmp/apache/cgi-bin/print
%request
Accept: */*
Accept-Language: en
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3
Connection: keep-alive
Host: 192.168.1.3:8080
%response
Script /cgi-bin/print
%stdout
Script Location /var/tmp/apache/cgi-bin/print

Для загруженых web-сайтов и переживающих за место, которое может занимать log-файл, директива “ScriptLogLength” может служить для указания верхней границы лог-файла.

Отладка запросов и ответов

При поддержке веб-приложений бывает, когда проблема может быть
вызвана сервером приложений, прокси-сервером или самими сервером. Для решения даного типа проблем, полезно получить копию (дамп) HTTP-запросов и ответов чтобы изолировать проблему к локальной или удалённой системе. Модуль apache mod_dumpio может быть использыван для этой цели, так как он позволяет писать в error_log HTTP-запросы и/или HTTP-ответы.

Настройка mod_dumpio проста. Для получения HTTP-запросов в error_log нужно установить директиву “DumpIOInput” в “On.” Для получения HTTP ответов в error_log директива “DumpIOOutput” должна быть в “On.” Если одна с этих директив включена, то каждый раз когда приходить запрос или отправляется ответ происходит такая запись в error_log:

Sat Oct 28 10:52:31 2006] [debug] mod_dumpio.c(103): mod_dumpio: dumpio_in [getline-blocking] 0 readbytes

[Sat Oct 28 10:52:31 2006] [debug] mod_dumpio.c(51): mod_dumpio: dumpio_in (data-HEAP): 16 bytes
[Sat Oct 28 10:52:31 2006] [debug] mod_dumpio.c(67): mod_dumpio: dumpio_in (data-HEAP): GET / HTTP/1.1rn < ..... >

Mod_dumpio добавляет некоторые дополнительные рассходы на обработку запроса и требует перегрузки сервера для применения настроек (вы можете использовать постепенный рестарт без закрытия активных соединений).

Определение почему процесс apache “завис”

Apache подвергается серьёзному тестированию каждого релиза, но периодично ошибки подкрадаются к QE процессу (Прим. пер. Не знаю что это). Это может проявляться как “зависший” web-сервер, сильный крах и неправильный контент, который возвращается пользователям. Когда эти проблемы появляются, важно быть в состоянии быстро идентифицировать источник проблемы (например, модуль, основной сервер, и т.д).

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

Есть несколько инструментов, которые могут использоваться для получения трассировки стека. Одним из инструментов является pstack, которое печатает трассировку стека для процесса, идентификатор которого следует передать в качестве аргумента:

$ pstack 18756
18756:  bin/httpd -k start
ff040628 accept (3, 11c560, 11c54c, 1)
0004c3c4 unixd_accept (ffbff904, 7d490, 11c3a0, 0, 2710, 0) + 10
0004a3c0 child_main (7d490, 74400, 4e2e, 74000, 0, 74000) + 2ec
0004a6c8 make_child (4a000, 0, 1, 5, 72c00, 74000) + ec
0004b0e8 ap_mpm_run (72c00, 74000, 74000, 74000, 74000, 74400) + 934
000272d8 main (7ef18, 71c00, 73800, 73800, 0, 0) + 710
00026618 _start (0, 0, 0, 0, 0, 0) + 5c

В платформах, в которых нет утилиты pstack, можно воспользоватся gdb и gcore. Для подключения непосредственно к процессу отладчика и для получения трассировки стека, gdb нужно запустить с параметром “-p” и идентификатором процесса; так же команду “backtrace” можно запустить с shell самой утилиты gdb:

$ gdb -q -p 2575 (gdb) backtrace
#0  0x0046e7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x0063b681 in accept () from /lib/tls/libpthread.so.0
#2 0x00b14814 in apr_socket_accept (new=0xbff85740, sock=0x9671538,
connection_context=0x97115d8) at network_io/unix/sockets.c:187
#3 0x080819ce in unixd_accept (accepted=0xbff85774, lr=0x9671518, ptrans=0x97115d8) at unixd.c:466
#4 0x0807fd2e in child_main (child_num_arg=Variable "child_num_arg" is not available.) at prefork.c:621
#5 0x0807ffc2 in make_child (s=Variable "s" is not available.) at prefork.c:736
#6 0x08080050 in startup_children (number_to_start=5) at prefork.c:754
#7 0x0808089b in ap_mpm_run (_pconf=0x96730a8, plog=0x96a1160, s=0x9674f48) at prefork.c:975
#8 0x08061b08 in main (argc=3, argv=0xbff85a84) at main.c:717

Каждая трассировка будет содержать много частей полезной отладочной информации, но нахождение причины зависшего сервера, как правило, требует рассмотрения каждого фрейма стека, которые привели к текущему фрейму и избирательно получить дамп структуры данных сервера. Отладка таким образом занимает много времени, и не подходит для сайтов, которые требуют постоянной работоспособности. Для помощи в анализе первопричины и offline отладке, можно использовать для генерации основного файла зависшего сервера утилиту gcore. Этот файл может проанализировать системный администратор или поставщик операционной системы, чтобы определить почему зависает web-сервер.

В следующем примере показано, как пользоваться утилитой gcore, чтобы сделать дамп ядра при зависании и потом показывает как использовать утилиту gdb для получения трассировки стека с файла ядра:

$ gcore 5649 $ gdb -q /usr/sbin/httpd core.5649 (gdb) backtrace
#0  0x0046e7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x0063b681 in accept () from /lib/tls/libpthread.so.0
#2 0x00b14814 in apr_socket_accept (new=0xbff85740, sock=0x9671538,
connection_context=0x97115d8) at network_io/unix/sockets.c:187
#3 0x080819ce in unixd_accept (accepted=0xbff85774, lr=0x9671518, ptrans=0x97115d8) at unixd.c:466
#4 0x0807fd2e in child_main (child_num_arg=Variable "child_num_arg" is not available.) at prefork.c:621
#5 0x0807ffc2 in make_child (s=Variable "s" is not available.) at prefork.c:736
#6 0x08080050 in startup_children (number_to_start=5) at prefork.c:754
#7 0x0808089b in ap_mpm_run (_pconf=0x96730a8, plog=0x96a1160, s=0x9674f48) at prefork.c:975
#8 0x08061b08 in main (argc=3, argv=0xbff85a84) at main.c:717

В выше описанных примерах с pstack, gdb и gcore, можно увидеть что apache находится в системном вызове accept() когда был послан сигнал SIGSEGV и accept() вызван портативным методом во время выполнения apr_socket_accept (). Если бы проблема присутствовала в сервере, то эти методы могут быть в базе данных ошибок и насколько это известная ошибка. Для получения дополнительной информации о передовых методах отладки, смотрите ссылки.

Определение почему процесс apache вызвал сбой

Если apache вызвал сбой из-за нарушение сегментации (segmentation violation),инструменты, такие как gcore и pstack не помогут,поскольку этот процесс был вынужден выйти. Перед выходом процесса, главный файл, как правило, пишется в каталог, который определен в директиве ServerRoot. Для того чтобы основной файл мог быть записан в этот каталог, user-ID процесса, под которым он запущен, должен иметь право записи в этот каталог и “core file size” resource limit должен быть установлен в достаточно большое значение, чтобы можно было создать основной файл. Если политика безопасности запрещает право записи пользователям в ServerRoot, тогда для контроля записи основных файлов можно воспользоваться директивой “CoreDumpDirectory” .

На некоторых платформах этого по-прежнему недостаточно, так как основные файлы надежно не генерируется. Если у вас проблемы на сервере на таких платформах, модуль mod_backtrace может помочь в неспособности платформы создавать надёжные core files. Mod_backtrace работает, позволяя обработчик сигнала для каждого не восстанавливаемого сигнала (например, SIGSEGV, SIGBUS, и т.д.). Когда получен один с не восстанавливаемых сигналов, mod-backtrace вызывает спецефический платформенный вызов для генерации отладочного стэка процесса и записывает его в лог ошибок (error_log).

Mod_backtrace доступен в исходных кодах и может быть получен с сайта apache:


$ wget http://people.apache.org/~trawick/mod_backtrace.c

Для компиляции исходного кода и установки модуля в директорию модулей apache, вызывается утилита apache apxs с параметром “-c” для компиляциии с опцией “-i” для установки:


$ apxs -ci mod_backtrace.c

Для того, чтобы использовать модуль mod_backtrace, apache должен быть скомпилирован с exception hook (Прим. пер. не знаю, что это такое). Это можно включить в скрипте конфигурирования configure с помощью опции “–enable-exception-hook”. Когда модуль будет скомпилирован, подключен и exception hook активным, модуль mod_backtrace можно будет загрузить директивой “LoadModule”, а так же следует включить директиву “EnableExceptionHook”. Ниже показан пример директив для корректной работы mod_backtrace:

LoadModule backtrace_module modules/mod_backtrace.so 
EnableExceptionHook On

После того, как модуль будет работать, и каждый раз, когда apache будет вызывать критический сигнал, в error_log будет писатся что-то похожее:

$ kill -SIGSEGV 18745
[Wed Dec 20 16:48:32 2006] pid 18745 mod_backtrace backtrace for sig 11 (thread "pid" 18745)
[Wed Dec 20 16:48:32 2006] pid 18745 mod_backtrace main() is at 26bc8
/var/tmp/apache/modules/mod-backtrace.so:bt_exception_hook+0x108
/var/tmp/apache/bin/httpd:ap_run_fatal_exception+0x34
/var/tmp/apache/bin/httpd:0x32788
/lib/libc.so.1:0xc01dc
/lib/libc.so.1:0xb52d4 /lib/libc.so.1:_so_accept+0x8 [ Signal 11 (SEGV)]
/var/tmp/apache/bin/httpd:unixd_accept+0x10
/var/tmp/apache/bin/httpd:0x3a3c0
/var/tmp/apache/bin/httpd:0x3a6c8
/var/tmp/apache/bin/httpd:0x3a798
/var/tmp/apache/bin/httpd:ap_mpm_run+0x9d4
/var/tmp/apache/bin/httpd:main+0x710
/var/tmp/apache/bin/httpd:_start+0x5c
[Wed Dec 20 16:48:32 2006] pid 18745 mod_backtrace end of backtrace

Mod_backtrace использует подпрограмму backtrace() на системах GNU, и метод printstack () на системах Solaris, чтобы программно получить backtrace. В некоторых случаях символьные имена не могут быть получены правильно. Если это случается, могут использоваться утилиты nm, readelf и elfdump, чтобы дополнить информацию, предоставленную mod_backtrace. Чтобы использовать mod_backtrace на хостах с Solaris надо применить патч для исходного кода mod_backtrace. Ссылку на него можно поссмотреть в низу статьи.

Отладка с maintainer mode и макросами GDB

Отладка прикладных ошибок с помощью основных файлов (core files) является изобразительным искусством. Разработчики apache поняли, что для отладки сбоев apache нужны хорошие инструментальные средства, и интегрировали две ключевые особенности в помощь отлаживающему. Первая особенность – maintainer mode в Apache, который составляет сервер с отладочными метками, без оптимизации. Это полезно когда используется отладчик исходников с web-сервером, так как функции не будут оптимизированы и исходный текст C может быть отображен в отладчике. Для включения этой возможности, нужно включить флаг конфигурации “–enable-maintainer-mode” когда будете компилировать.

Вторая возможность – набор макросов GDB. Эти макросы позволяют вам просто проссматривать состояние структуры данных apache (например, цепочки фильтров, области памяти и бригады, и т.д.), которые полезны для отладки основного файла после смерти. Макроопределение расположены в файле .gdbinit, который расположен в корне каталоге исходного кода Apache. Если вам интересны макросы, можете проссмотреть 2 презентации в ниже в ссылках.

Использование исходного кода для отладки ошибок

Когда log-файлы, core-файлы и системные утилиты неспособны точно определить проблему с Apache, обращение к исходному коду может быть полезным. Исходный код web-сервера организован как иерархия каталогов и каждая директория содержит исходный код для некоторого средства (например, модулей, portable runtime и т.д.). В релизе 2.2.3, исходный код разделён на следующие каталоги:

  • $SRCROOT/server – содержит исходный код основного сервера
  • $SRCROOT/include – содержит заголовочные файлы основного сервера
  • $SRCROOT/srclib/apr – содержит исходный код portable runtime-среды
  • $SRCROOT/srclib/apr-util – содержит исходный код portable runtime-утилит
  • $SRCROOT/support – содержит исходный код утилит
  • $SRCROOT/modules – содержит исходный код модулей

Если stacktrace или сеанс отладки показывают, что определенная подпрограмма вызывает ошибку, можно воспользоваться поиском, чтобы определить местонахождение кода C, который включает ту функцию (или макрокоманду). Чтобы найти определение функции apr_array_make , можно воспользоваться таким списком команд, например:

$ find . -name \*.h | xargs egrep "apr_array_make"
./srclib/apr/include/apr_tables.h:APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p, ...
< ... >

Когда определён прототип функции, можно воспользоваться утилитами find и grep для определения файла с исходным кодом определения функции:

$ find . -name \*.c | xargs egrep "apr_array_header_t.*apr_array_make"
/srclib/apr/tables/apr_tables.c:APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p, ...
< ... >

Согласно вывода функций, прототип функции the apr_array_make находится в файле apr_tables.h и определение её в файле apr_tables.c. В зависимости от того, как определены функции (и макросы), результаты могут потребовать некоторой дополнительной визуальной обработки.

Заключение

Как администраторы веб-серверов, мы стараемся принять необходимые меры к тому, что наши серверы работали 24×7. Это не всегда возможно и хорошие инструменты для диагностики проблем является необходимостью. Эта статья обсуждала несколько инструментальных средств, которые могут помочь с отладкой и описано несколько методик, которые могут использоваться, чтобы определить местонахождение проблем с веб-сервер Apache. Если у вас есть вопросы и комментарии к этой статье, то можете написать на e-mail автору.

Ссылки

Для написание статьи использовались следующие материалы:

Благодарности

Ryan хотел бы поблагодарить разработчиков apache за их вклад в наиболее популярный веб-сервер.

* Оригинал напечатан в “SysAdmin Magazine” July ’07 issue.

Categories: life Tags:
  1. No comments yet.
  1. No trackbacks yet.