Где проводится профессиональная переподготовка "Системное администрирование Windows"? Что-то я не совсем понял как проводится обучение. |
Практическое применение DTrace
Однажды у нас был случай, когда скрипт на php непостижимым образом выдавал лишнюю пустую строку в генерируемой странице. А страница импортировалась в поток RSS у разных хороших людей. То есть должна была, но не импортировалась, потому что лишняя пустая строка все портила. Тогда дело решилось внимательным изучением всех включаемых файлов .php и обнаружением лишней строки. Однако бывают и более сложные случаи, когда при отладке web-приложений хочется понять, как на самом деле это приложение работает. Сейчас очень многие веб-сайты, даже довольно простые, строятся на основе системы управления контентом (CMS, content management system). И еще многие другие – просто на связке php-скрипт – база данных. С другой стороны, а именно со стороны клиента, заполнение разнообразных форм на веб-странице обычно связано с кодом на javascript, так как это – стандартный способ проверять допустимость значений в полях формы.
Можем ли мы в отладке веб-приложений применить DTrace для того, чтобы отследить все передаваемые от веб-обозревателя к базе данных (и обратно) параметры на всем пути их следования через скриптыобработчики? Если мы используем Solaris – то да. И более того, легко.
Вспомним, что технология DTrace в настоящее время воплощена в Solaris (начиная с Solaris 10) и портирована в Mac OS X Leopard, FreeBSD 6.2 (частично) и QNX Neutrino (QNX6). В данной статье мы рассматриваем ее применение в Solaris и помним, что приложения третьих компаний (например, Firefox) в виде готового пакета для других систем с поддержкой DTrace могут быть еще недоступны для скачивания. Однако если вы хотите инструментировать любое приложение с открытым кодом, используя DTrace, никто не вправе помешать вам. Описание того, как это сделать с помощью провайдера sdt (statically defined tracing), можно найти на странице http://www.solarisinternals.com/wiki/index.php/DTrace_Topics_USDT.
Приводимые в статье примеры основаны на наборе DTrace Toolkit, который состоит из 386 скриптов (количество верно для версии DTrace Toolkit 0.99) на языке D и содержит скрипты почти на все случаи жизни, начиная с простых примеров и продолжая трассировкой java-приложений, о которой можно написать отдельную статью. Скачать DTrace Toolkit можно по адресу http://www.opensolaris.org/os/community/dtrace/dtracetoolkit/
Каждый датчик, по срабатыванию которого мы можем выполнять требуемые нам действия в D-скрипте, относится к определенному провайдеру. Системным провайдерам (типа syscall, io и пр.) соответствует одноименный модель ядра, а за провайдеры, созданные сторонними разработчиками, отвечает модуль ядра sdt. Это вам, скорее всего, уже известно из предыдущей статьи про DTrace в декабрьском номере "Системного администратора" (а может быть, вы это узнали еще раньше?) Теперь мы изучим возможности, которые нам предоставляет провайдер javascript, а в следующем разделе разберемся с провайдерами php и postgresql.
Провайдер javascript
В свежих сборках Firefox (забирать по адресу http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/contrib/latest-trunk/) в код вставлены датчики DTrace. Из D-скриптов к ним надо обращаться через провайдер javascript. Для экспериментов мы выбрали firefox-3.0a9pre.en-US.solaris11-i386.tar.bz2. Кстати, имейте в виду, что более старые версии firefox могли включать этот же провайдер под другим именем – mozilla.
Что именно позволяет посмотреть провайдер javascript?
# dtrace -l -n 'javascript*:::'|more ID PROVIDER MODULE FUNCTION NAME 72803 javascript2258 libmozjs.so jsdtrace_execute_done execute-done 72804 javascript2258 libmozjs.so js_Execute execute-done 72805 javascript2258 libmozjs.so jsdtrace_execute_start execute-start 72806 javascript2258 libmozjs.so js_Execute execute-start ... (вывод команды сокращен)
Как видно из вывода dtrace, имя провайдера появляется сопряженным с идентификатором процесса firefox-bin, а датчики вводятся для ряда основных функций. Также есть датчики function-entry, funtion-info, function-return, function-rval, object-create, object-create-start, object-createdone и object-create-finalize. Набор датчиков в будущем может быть расширен, но в той версии mozilla, которая оказалась в нашем распоряжении, других датчиков не было.
Какой толк можно получить из срабатывания этих датчиков? Во-первых, можно традиционно трассировать выполнение функции, написанной на javascript, и мерять время выполнения разных ее компонент. Во-вторых, уже сейчас доступна экспериментальная функциональность провайдера javascript по трассировке функций с выводом их аргументов.
Детальную информацию об аргументах датчиков, предназначенных для этого, можно почерпнуть на странице http://news.speeple.com/blogs.sun. com/2007/10/23/dtrace-mozilla-rfe-javascript-tracing-framework-landed.htm:
javascript*::: function-args Args: (char *filename, char *classname, char *funcname, int argc, void *argv, void *argv0,void *argv1, void *argv2, void *argv3, void *argv4) javascript* :::function-rval Args: (char *filename, char *classname, char *funcname, int lineno, void *rval, void *rval0)
Датчик function-args служит для показа аргументов вызванной javascript-функции в скрипте, а function-rval – для показа возвращаемого функцией значения.
Кстати, если под рукой нет документации, то некоторое представление о том, какие аргументы есть у датчика, и следовательно, какие параметры arg0..argN вам требуется выводить командой printf в скрипте, можно получить, используя ключи -l -v команды dtrace (только давать их надо перед ключом -n, если вы его применяете, это важно!)
dtrace -l -v -n 'javascript*:::function-args' 72808 javascript2258 libmozjs.so js_Interpret function-args Probe Description Attributes Identifier Names: Private Data Semantics: Private Dependency Class: Unknown Argument Attributes Identifier Names: Private Data Semantics: Private Dependency Class: Unknown Argument Types args[0]: char * args[1]: char * args[2]: char * args[3]: int args[4]: void * args[5]: void * args[6]: void * args[7]: void * args[8]: void * args[9]: void *
Как видно, датчик function-args может иметь до 9 аргументов, смысл которых пояснен выше, а при определенном воображении о значении аргументов можно догадаться по их типу. Так или иначе, команду dtrace -l -v стоит иметь в виду.
Попробуем выяснить с помощью датчика function-args, какое значение из формы в файле .html передается в написанную нами функцию на javascript. Наш экспериментальный файл и код javascript представляют собой проcтую форму для ввода единственного поля – даты и проверку на формат даты соответственно:
<html> <head> <title>Input form</title> <script language="JavaScript" type="text/javascript"> function testDate(date) { alert(date); return(true); } function testBox1(form) { /* Parsing of date and time */ IDate = form.date.value; if (testDate(IDate)) return (true); return (false); } function runSubmit (form, button) { if (!testBox1(form)) return; document.inputform.submit(); // un-comment to actually submit form return; } </script> </head> <body> <form name="inputform" action="/cgi-bin/main.pl"> <input name="date" type="text" size="8"></td> <input type="button" name="act" value="Submit" onClick="runSubmit(this.form, this)"> </form> </body> </html>
Функция testDate в этом примере фактически не проверяет дату, а лишь выдает ее значение в окне сообщения, однако вместо такой заглушки можно написать честную проверку. Для демонстрации работы с dtrace она нам не понадобится. В скрипт /cgi-bin/main.pl передаются введенные данные из поля. Листинг main.pl мы не приводим, так как сейчас он не имеет для нас значения – мы изучаем работу функции проверки данных на стороне клиента, а скрипт main.pl работает на сервере.
Запускаем firefox-bin с включенными в него датчиками, открываем файл с вышеприведенным кодом и переходим к эксперименту:
# dtrace -n 'javascript*:::function-args /copyinstr(arg2) == "testDate"/ {printf("%s %s %d %s",copyinstr(arg0),copyinstr(arg2),arg 3,copyinstr(arg5));}' dtrace: description 'javascript*:::function-args ' matched 4 probes CPU ID FUNCTION:NAME 1 18348 jsdtrace_function_args:function-args file:///export/home/ filip/jstest.html testDate 1 00.00.00
Как видно из вывода нашего скрипта, в качестве даты мы вводили значение 00.00.00. Будем надеяться, что настоящая функция проверки даты такого безобразия не пропустит!