XDebug или краткое введение в отладку PHP скриптов

В этой статье будет рассказано о том как производится отладка, трассировка и профилирование PHP скриптов в ОС Линукс при помощи специального расширения PHP - xdebug, которое было создано одним из разработчиков языка PHP Derick Rethans. Статья не претендует на полноту раскрытия такой обширной темы как отладка кода, но все же будет полезна начинающим PHP программистам, которые только начинают знакомство с основными инструментами отладки.

Установка xdebug

Первое что следует сделать перед началом работы - установить расширение. Перед установкой проверьте что версия PHP >= 4.3 (с более старыми версиями расширение не работает, но, в подавляющем большинстве случаев, это уже не требуется)ю В популярных дистрибутивах Линукс установка этого расширения очень проста. В зависимости от типа вашего дистрибутива запустите с правами root одну из следующих команд:

  • Для Debian/Ubuntu - aptitude install php5-xdebug
  • Для Fedora/CentOS/RedHat - yum -y install php-pecl-xdebug
  • Для Gentoo - emerge dev-php5/xdebug

Если ваш дистрибутив не входит в число перечисленных выше или установка из репозитория по какой-либо причине недоступна, то остается вариант скомпилировать расширение из исходников. Для этого нужно скачать с оффсайта Xdebug архив с последней версией расширения, распаковать архив, перейти в папку с деревом исходников и запустить компиляцию:

phpize
./configure --enable-xdebug
make

В случае успешного окончания компиляция в директории modules/ будет создан файл xdebug.so - это и есть нужное расширение. Теперь его нужно скопировать в папку с расширениями php и добавить в файл конфигурации Apache строчку extension=xdebug.so.

После того как расширение будет установлено любым из вышеперечисленных способов - перезапустите Apache! Для проверки того что расширение установлено успешно можно создать в любом из VirtualHost’ов Apache файл info.php с таким содержанием:

<?php
phpinfo();
?>

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

Настройка xdebug

Полное описание доступных опция настройки расширения может быть темой отдельной статьи. Для тех кто впервые знакомится с отладкой PHP я советую следующий конфиг:

extension=xdebug.so
 
[debug]
; Remote settings
xdebug.remote_autostart=off
xdebug.remote_enable=on
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_host=localhost
xdebug.remote_port=9000
 
; General
xdebug.show_local_vars=On
xdebug.dump.SERVER=HTTP_HOST, SERVER_NAME
xdebug.dump_globals=On
xdebug.collect_params=4
xdebug.auto_trace=off
xdebug.collect_includes=on
xdebug.collect_return=off
xdebug.default_enable=on
xdebug.extended_info=1
xdebug.manual_url=http://www.php.net
xdebug.show_mem_delta=1
xdebug.max_nesting_level=100
xdebug.idekey=netbeans-xdebug
 
; Trace options
xdebug.trace_format=0
xdebug.trace_output_dir=/var/www/debug
xdebug.trace_options=0
xdebug.trace_output_name=tracelog
 
; Profiling
xdebug.profiler_append=0
xdebug.profiler_enable=0
xdebug.profiler_enable_trigger=0
xdebug.profiler_output_dir=/var/www/debug
xdebug.profiler_output_name=scriptprofile.out

Глобальные настройки расширения, которые будут действовать для всех сайтов добавляются в конфиг php.ini. Настройки для отдельных сайтов можно указывать в файлах .htaccess при помощи директивы php_value или даже в самих скриптах php вызовом ini_set().

Получение информации о работе скрипта

Сразу после того как расширение будет установлено вы уже сможете заметить некоторые изменения в виде улучшения вывода ошибок языка PHP в браузере или изменившийся вывод var_dump(). Но этим возможности расширения, конечно, не ограничиваются. Если вы используете приведенный выше конфиг, то к стандартному сообщению об ошибке будут дополнительно выводиться значения локальных переменных, глобальных переменных и содержимое массива $SERVER. Также можно добавить вывод значений переменных которые передаются в скрипт методом GET или POST. Для этого добавьте в конфиг строки xdebug.dump.GET=* или xdebug.dump.POST=*.

Предупреждение: расширенный вывод в случае ошибок будет работать только если в конфигурации PHP установлен параметр display_errors в On и если вы не переопределили стандартный обработчик ошибок на свой при помощи register_error_handler()

Для того чтобы лучше понять содержание предыдущего абзаца советую временно прервать чтение статьи и запустить на настроенном веб-сервере небольшой скрипт, например такой:

<?php
function foo() {
	$a = 1;
	return $a;
}
 
$b = bar();
 
?>

После запуска этого скрипта вместо стандартного сообщения о попытке вызова несуществующей функции Fatal error: Call to undefined function bar() черными буквами на белом фоне вы увидите симпатичную табличку, которая также будет содержать множество дополнительной, полезной при отладке скрипта информации. Таким образом, уже просто само наличие установленного расширения избавляет программиста от необходимости добавлять в код так называемый отладочный вывод.

Трассировка скрипта

Часто во время отладки скрипта возникает необходимость не только узнать значения переменных в момент возникновения фатальной ошибки как было показано в предыдущем параграфе, но и восстановить точную последовательность вызовов функций и обращений к методам класса. В этом нам поможет ведение лога трассировки, который представляет собой запись в специальный указанный файл всех вызовов во время работы программы. Включить режим трассировки можно как глобально (для всех запущенных скриптов и на все время их работы) - для этого добавьте в вышеприведенный конфиг строку xdebug.auto_trace=On или включать только для отдельных участков отлаживаемого кода - добавьте в php-код вызов функции xdebug_start_trace(’/путь/файл’) в начале участка и xdebug_stop_trace() в конце. Поскольку ведение лога сильно замедляет работу веб-приложения я советовал бы выключить запись в лог глобально и включать его на время только для нужного участка кода, как это и сделано в примере конфигурации из этой статьи. Теперь достаточно перезапустить скрипт и все вызовы функций в выбранной участке программы будут записаны в указанный лог.

Для примера возьмем такой код:

//эта функция не выполняет никакой полезной работы, но на ее примере
//можно увидеть как в логе трассировки отображаются переданные
//параметры и возвращаемое функцией значение
function formatted_output($n) 
{
  echo $n . '<br>';
  return $n . ' - success';
}
 
//включить в лог трассировки возвращаемое функцией значение
ini_set ('xdebug.collect_return', 1);
//включить в лог трассировки параметры функции
ini_set ('xdebug.collect_params', 4);
 
//запустить запись в лог
xdebug_start_trace('/var/www/debug/funcs');
 
for ($i=0; $i<10; $i++) {
  formatted_output($i);
 }
 
//остановить запись в лог
xdebug_stop_trace();

В итоге мы получим примерно вот такой лог. В нем видны вызовы функции из выбранного участка кода, параметры каждого вызова и результат работы.

TRACE START [2009-05-19 00:04:59]
    5.0023      65836     -> formatted_output($n = 0) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '0 - success'
    5.0025      65912     -> formatted_output($n = 1) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '1 - success'
    5.0027      65948     -> formatted_output($n = 2) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '2 - success'
    5.0028      65984     -> formatted_output($n = 3) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '3 - success'
    5.0029      66020     -> formatted_output($n = 4) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '4 - success'
    5.0030      66056     -> formatted_output($n = 5) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '5 - success'
    5.0031      66092     -> formatted_output($n = 6) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '6 - success'
    5.0032      66128     -> formatted_output($n = 7) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '7 - success'
    5.0033      66164     -> formatted_output($n = 8) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '8 - success'
    5.0034      66200     -> formatted_output($n = 9) /var/www/localhost/htdocs/xdebug.php:12
                           >=> '9 - success'
    5.0036      66236     -> xdebug_stop_trace() /var/www/localhost/htdocs/xdebug.php:42
    5.0036      66236
TRACE END   [2009-05-19 00:04:59]

Наиболее удобным способом включения трассировки для скрипта является, на мой взгляд, добавление к адресу скрипта дополнительного аргумента ?XDEBUG_SESSION_START=1. В этом случае для включения режима отладки даже не требуется изменять исходный текст программы.

Профайлинг

И еще одно, последнее на сегодня, полезное применение расширения XDebug - профайлинг кода.

Включение профайлинга позволяет оценить как долго выполняется та или иная часть кода по отношению к общему времени выполнения скрипта. Для профайлинга я советую использовать такой же подход как и с трассировкой: выключить выполнение глобально по умолчанию (xdebug.profiler_enable=0), но оставить возможность включать для отдельных скриптов через добавление к урлу специального GET-параметра ?XDEBUG_PROFILE=1. Просто укажите в настройках xdebug.profiler_enable_trigger=1 и получить лог с результатами профайлинга можно будет введя в строке адреса браузера урл вида http://localhost/script.php?XDEBUG_PROFILE=1.

Два оставшихся параметра подобны аналогичным опциям для трассировки, которые были описаны выше.

xdebug.profiler_output_dir=/var/www/debug
xdebug.profiler_output_name=scriptprofile.out

Первая строка указывает путь к директории для сохранения лога профиля, вторая - имя файла.

Однако у лога профайлинга есть одно важное отличие от лога трассировки - он не предназначен для чтения человеком-программистом и для его просмотра потребуется специальная программа - KCacheGrind, которая легко устанавливается из репозитория.

Если вам понравился этот сайт, вы можете подписаться на rss

Отзывы: Комментариев нет

Ваш отзыв

Имя (*)

E-mail (*)

Сайт

Сообщение

Архивы

службы мониторинга серверов