Несколько советов по отладке
CGI-программы -не самые простые в отладке,по сложности отладки они способны сравнится лишь с отладкой драйверов. Вся сложность заключается в том,что скрипт выполняется не как обычная программа. Он выполняется в специальной среде сервера,которая создается при клиентском запросе, к тому же он исполняется не из под вашего аккаунта,а на непривилегированом уровне.
Если скрипт не исполняется потому,что вы допустили синтаксические ошибки,то самих этих ошибок вы не увидите,на экране будет только 'Internal Server Error' из-за чего она произошла вы можете только гадать. Также если вы забыли задать к какому-то файлу нужные ,то тоже будет трудно выяснить что же произошло и в чем причина ошибки (если конечно к этому вы не готовы).
Ну вот ,хватит вас пугать,тем более что нас не запугаешь ;) !
Приступим к отладке.Я вам опишу достаточно примитивные меры,которыми я сам пользуюсь.
Начнем с того что у нас есть скрипт test.cgi мы уже сделали его исполняемым chmod +x test.cgi
Простейший способ проверить его на ошибки это команда perl -c test.cgi
Ключ -c говорит Perl что надо только проверить синтаксис.Все сообщения об ошибках вы можете видеть и подправить.Более тяжелый случай состоит в том когда Perl встроен в Web -Сервер, причем версии разные.Как у до недавнего времени было на uic'е ;(( ! Тот Perl с которым работаем в командной строке
4й версии ,а на сервере стоит 5й версии.Если ваша CGI-программа использует при этом какие-нибудь преимущества 5-й версии (например обьектно-ориентированые модули),то вы думаете отладить ее низ -ошибаетесь!.Только приготовтесь к тому, что я сейчас скажу,вы сядте,а то упадете ;)) :
Закоментируйте всю вашу программу ,т.е. перед каждой строчкой поставьте символ '#'. После чего,добавьте вот такие строчки: print "Content-Type: text/html\n\n";
print "<HTML>Test</HTML>"; exit; ,Должно получится так:
#!/usr/bin/perl #test.cgi print "Content-Type: text/html\n\n"; print "<HTML>Test</HTML>"; exit; #Программа как вы понимаете выполняется только до етого места # #if($ENV{'REQUEST_METHOD'} eq 'GET'){$query=$ENV{'QUERY_STRING'}} #else{sysread STDIN,$query,$ENV{'CONTENT_LENGTH'};} #if($query eq ''){ # @formfields=split /&/,$query; # ....... # ........
А теперь запускайте скрипт. Естественно он выдаст Одно только слово 'Test'. Разкоментируйте несколько строчек.Еще раз запустите скрипт.Он опять выдаст 'Test'. Значит синтаксически эти только что разкоментированые строчки были правильные. И так далее....
Если очередной раз после раскоментирования вы запустили скрипт и получили 'Internal Server Error' - значит в этих строках содержалась какая-та синтаксическая ошибка. Это способ отловки синтаксических ошибок трудоемок,но к нему придется прибегнуть если ваш скрипт писан под ту версию Perl,что на сервере,а не под ту что у вас.
Узнать версию Perl можно perl -v
Ну вот мы отловили в нашем скрипте все синтаксические ошибки,он заработал, но это не значит,что он работает правильно.
Что еще можно посоветовать при отладке CGI-скриптов от ошибок возникающих во время выполнения программы. Допустим какой-то файл не открылся.Конечно показывать перепуганому пользователю эти технические подробности никчему,поэтому заведите себе специальный файл debug.txt
и пусть ваши скрипты пишут в этот файл причины своих ошибок и сбоев, да и вообще о всех непредвиденых событиях.
Это можно реализовать так:
sub debug_err{ open(DEBUGFILE,">>debug.txt"); print DEBUGFILE $ENV{'SCRIPT_NAME'}.' '.scalar localtime.' '.@_."\n"; close(DEBUGFILE); }
Примеры использования (Напомню,что встроеная переменная Perl $! содержит сообщение о причине последней ошибки,поэтому включайте ее всегда в свои сообщения):
open(F,"+<$myfile") debug_err("Cannot open $myfile $!"); seek(F,0,0) debug_err("Cannot seek $myfile $!"); connect(SOCKET,$paddr) debug_err("Cannot connect to $remote $!"); ......
Потом можно периодически заглядывать в этот файл debug.txt и смотреть,какие ошибки встречались при работе ваших скриптов.Таким образом ваши скрипты сами помогать будут в своей отладке ;).
Также очень может оказать помощь (может и не оказать) просмотр http'шных логов. Все обращения к URL на сервере и все возникающие при этом ошибки идут в логи сервера httpd. Сразу хочу предупредить - размеры этих логов даже на средних размеров сервере достигает десятков мегабайт. Поэтому даже не пытайтесь их вот так просто посмотреть.- Лучше если вы уж за данное дело взялись - воспользуйтесь такими утилитами как grep,head,tail,more,less. .
Кстати я хочу сказать о причине еще одной (совсем не очевидной) ошибки.Если вы набрали скрипт у себя дома на компутере, то полученый скрипт состоит из текста в DOS'ом формате, а не в Unix'ом так что имейте это ввиду. Запускать вам его придется в системе Unix , так что следует перевести програмный текст в нужный формат.
Дело в том что в системах DOS и Windows (это уж очередной раз скажите все что вы думаете о Билле Гейтсе и Ко) для разделения строк используетс не один "символ новой строки" ("\n"),а пара символов "возврат каретки" ("\r") и "символ новой строки" ("\n"). Для простых HTML-файлов это не критично - браузеры игнорируют такие символы при выводе. Но скрипт является ПРОГРАММОЙ. А в программе никаких символов возврата каретки быть не должно!! Особенно в первой строке. Потому что когда операционная система запускает скрипт, она определяет какое приложение запустить для обработки данного скрипта именно по первой строке. В первой строке как вы знаете содержится #!/usr/bin/perl или #!/usr/local/bin/perl .Поэтому при запуске скрипта mysrcipt (это кстати вы можете сами увидеть коммандами top и ps) Система запускает комманду /usr/bin/perl mysript .А теперь представьте что будет если не убрать символ возврата каретки из Windows-файла. Получиться #!/usr/bin/perl<возврат каретки> и естественно что такого приложения нет, и следовательно попытка выполнить коммаду /usr/bin/perl<возврат каретки> mysript ни к чему не приведет!!!
Как с таким злом бороться я раскажу в моей следующей главе.