|
ru.cgi.perl- RU.CGI.PERL ------------------------------------------------------------------ From : Sly Golovanov 2:5020/794.13 28 May 2001 05:00:01 To : All Subject : FAQ 2/3 -------------------------------------------------------------------------------- WWW-специфика ------------------------------------------------------------------------------ Q: Я положил скрипт на сервер, ввожу его путь в браузер, но вместо того, чтобы выполнять скрипт, браузер выводит его исходный текст. A: Чтобы сервер запускал скрипт и выдавал результаты его работы, необходимо объяснить серверу, что этот файл - исполняемый. Существующее в unix-системах понятие "атрибуты файла" отличается от атрибутов в DOS/Windows, и в unix исполняемый файл определяется не расширением, а атрибутом. Если сервер работает на unix-системе, необходимо проставить на файл атрибуты исполняемого файла. Это делает команда "chmod 0755 file", если вы работаете через telnet или ssh, или же продвинутый FTP-клиент типа CuteFTP или FAR ftp plugin. Атрибуты файла, который могут исполнять все желающие (в том числе и сервер), выглядят в буквенном представлении, как -rwxr-xr-x Если вы работаете в win32 среде, достаточно определить программу, запускающую файлы с расширением, которое вы даете скриптам - например, cgi. Для этого нужно в windows explorer'е дважды кликнуть по файлу .cgi, и выбрать perl\bin\perl.exe в качестве запускающей программы. Это помогло мне под Sambar-сервером, с apache-win32 не сталкивался. Q: При попытке запустить скрипт происходит Internal Server Error! Что это за ошибка? A: Это, строго говоря, просто сообщение об одной из ошибок, приведших к невозможности нормального выполнения скрипта. Чаще всего возникает в следующих случаях: 1) в первой строке отсутствует или неправильно указан путь к perl. обычно это #!/usr/local/bin/perl или #!/usr/bin/perl 2) Файл со скриптом содержит DOS-овые концы строк 0x0D 0x0A. В юниксе конец строки - только 0x0A. Чтобы исправить это, воспользуйтесь соотв. возможностью редактора FAR (shift-f2, as Unix text), или при закачке скрипта на ftp используйте ASCII-режим вместо бинарного. 3) Скрипт не выводит ничего во время работы, или не выводит заголовок. Hеобходимо, чтобы он выводил хотя бы content-type заголовок, например: print "Content-type: text/html\n\n"; print "All done"; Обратите внимание на двойной перевод строки в конце заголовка. Если у вас нет доступа к логу ошибок сервера, для отладки скрипта используйте директиву use CGI::Carp qw (fatalsToBrowser); В этом случае при фатальной ошибке, приводящей к завершению скрипта, эта ошибка будет видна вам в браузере. Q: Как узнать IP человека, вызвавшего скрипт? A: $ENV{'REMOTE_ADDR'} Q: Как узнать, с какой страницы идет ссылка на скрипт? A: $ENV{'HTTP_REFERER'} Q: Как узнать IP прокси, если через нее запустили скрипт? A: $ENV{'HTTP_VIA'} A1: Hекоторые прокси добавляют в конец заголовка строку типа ", via ProxyName", и в результате вместо переменной HTTP_VIA эту строку можно наблюдать в конце переменной $ENV{'HTTP_USER_AGENT'} Q: А можно ли узнать IP юзера, запустившего скрипт через прокси? A: $ENV{'HTTP_X_FORWARDED_FOR'}. Hо не все прокси обеспечивают IP сидящего за ними юзера. "Честные" прокси,- у провайдеров, например,- это делают. А некоторые халявные прокси-сервера, могут и не показывать IP сидящего "за" ними пользователя. Q: А какие еще значения есть у этой %ENV ? A: for (keys %ENV) { print "$_ = ${ENV{$_}}\n" } A1: То же самое, но по-другому записанное (более "перловое" решение): print join("<br>",map("$_ = $ENV{$_}", keys %ENV)); (пальцы... - прим. SLY) Q: Как запускать скрипт на сервере через определенные промежутки времени, или в определенное время суток, день недели, месяц?.. A: Это возможно, если есть шелл-доступ на сервер. Читайте man crontab Q: Как, зная ip, получить имя (DNS), за которым этот ip закреплен? A: Встроенная функция gethostbyaddr() Q: Что такое method GET, и что такое method POST? A: У меня секретов нет - слушайте, детишки. GET - передача параметров скрипту из строки location браузера. Пример: script.cgi?mode=aa&type=bb&length=12 Минусы этого метода: 1. Все параметры видны в строке. Если в кач-ве параметров передается пароль - получается дырка в безопасности 2. Длина данных, передаваемых таким методом, ограничена. 3. Hельзя передавать multipart form data, в т.ч. файлы через кнопочку "Browse" POST - передача данных скрипту через STDIN. Отсутствуют минусы метода GET. Обычно метод GET используется, когда скрипт вызывается со страницы через линк <a href=...></a>, а POST - при нажатии кнопки submit в форме. О получении параметров внутри скрипта читайте в следующем Q. Q: Как обрабатывать параметры, переданные скрипту? A: Используйте модуль CGI. Прочтите perldoc CGI , а для начала вот простой пример: use CGI; $q=new CGI(); $mode=$q->param('mode'); $q - объект, который имеет несколько методов и полей, относящихся к параметрам вызова, переменным окружения, cookie, и пр. Смотрите perldoc CGI. В $mode содержится значение параметра 'mode'. или проще: use CGI qw/:standard/; $mode=param('mode'); если вам не нужно несколько объектов. Q: Посоветуйте халявный хостинг с поддержкой CGI на perl A: www.virtualave.net free.prohosting.com www.hypermart.net www.netfirms.com Q: Что надо указать в заголовках HTTP-ответа CGI скрипта, выводящего содержимое, которое надо не показать на экране, а сохранить в файле с заданным именем, например 'data.zip' ? А то браузер сохраняет файл с именем скрипта. A: Content-Disposition: attachment; filename="filename.ext" ------------------------------------------------------------------------------ > Apache-специфика ------------------------------------------------------------------------------ Q: А как бы мне сделать, чтобы вывод моего скрипта обрабатывался SSI? A: Честно - никак. Почему - см. документацию на Apache. Однако, раз уж у нас есть Perl, нам, видимо (честно говоря, сам не пробовал), поможет CGI::SSI (если это CGI) или Apache::SSI (если mod_perl). Q: А как бы мне ограничить доступ к скрипту или директории только для умных и местных (способных взломать веб-сервер или знающих пароль)? A: В принципе, возможно множество различных решений. Стандартное делается средствами авторизационного механизма веб-сервера. Читайте документацию Apache на предмет директив Auth* и require, а также на предмет параметра AuthConfig директивы AllowOverride, а то будете потом удивляться, почему совершенно правильный .htaccess не работает. mod_perl позволяет вклиниться в фазы контроля доступа, аутентификации и авторизации, и написать свои обработчики. Для аутентификации и авторизации по базам данных существуют модули для mod_perl AuthenDBI и AuthzDBI (в свежих версиях они объединились в один модуль, Apache::AuthDBI), а простейший пример файловой авторизации: <Files "myscipt.cgi"> AuthType Basic AuthName My.Script.Very.Secure AuthFile /home/vasia/.htpasswd require valid-user </Files> Файл /home/vasia/.htpasswd может лежать (и это рекомендуется) в месте, недоступном для укачивания. Если положить его в такое место невозможно, надо защитить его от укачивания посредством <Files ".htpasswd"> deny from all </Files> или как минимум всё тем же паролем, только уже с require vasia. Его формат - имя:пароль, пароль зашифрован стандартным юниксовым crypt(), так что если нет доступа к команде htpasswd (например, нет шелла), то можно сгенерировать его перловым скриптом. Я, собственно, поначалу так и делал, пока не сообразил, что должна быть специальная программа... Ко всему этому рекомендуется помнить, что пароли Basic авторизации передаются по сети в незащищённом виде (base64-кодирование строки "имя:пароль"), а поля форм <input type=password> показываются звёздочками только в браузере, по сети же передаются как есть (вернее, опять же закодированными, но уже как URL). Поэтому, если вы не пользуетесь защищённым каналом (SSL), работать так с действительно конфиденциальными данными нельзя. ------------------------------------------------------------------------------ mod_perl ------------------------------------------------------------------------------ Q: Что такое mod+perl и зачем он нужен? A: Hа пальцах - модуль к серверу Apache, который предназначен в первую очередь для ускорения запуска скриптов. Вместо того, чтобы каждый раз при запуске скрипта запускался perl, компилировал скрипт и выполнял его, этот perl все время запущен, и висит в памяти. В памяти же находятся и уже откомпилированные до состояния исполняемого кода скрипты. Кроме этого он позволяет вмешиваться почти во все стадии работы сервера, от конфигурирования до различных стадий обработки запроса; он позволяет получать от Апача все данные о нём самом и о запросе, которые у того есть. Q: Что означает ругань "Value of $x will not stay shared at - line 5" и "Constant subroutine XXX redefined ..." при попытке запустить скрипт при помощи mod_perl? A: Это следствие различий между работой честного CGI-скрипта, когда для выполнения скрипта порождается новый процесс, а по завершении скрипта процесс завершается, и работой под управлением Apache::Registry - модуля эмуляции окружения CGI под mod_perl. Скрипт, исполняющийся под Apache::Registry, выполняется как функция в том же процессе, что и сам веб-сервер, и результат его компиляции кэшируется mod_perl'ом до обновления скрипта. Второе сообщение не страшно - оно всего лишь предупреждает, что определённая в скрипте функция была перекомпилирована при повторном выполнении (или при перекомпиляции? не помню) скрипта. А вот первое чревато неприятностями, и означает оно, что определённая в скрипте (теперь - функции где-то внутри Apache::Registry) функция пользуется определённой в нём же лексической (my) переменной, не получая её среди аргументов. Такая функция называется closure (вернее, closure называется такая же, но анонимная функция), и смысл её в том, что значение этой переменной на момент определения функции сохраняется в ней, и в дальнейшем при обращении к ней она будет пользоваться этим сохранённым значением (в нашем случае - тем, которое приняла переменная при первом запросе к данному скрипту в данном экземпляре Апача), а не новым. Лечится это двумя различными способами: если этот скрипт уже более-менее отлажен и используется часто, полезно перенести определения функций из него в отдельный модуль; если же он пока отлаживается, то см. следующий вопрос. Q: Hаписание скриптов под mod_perl чем нибудь отличается от написания обычных CGI скриптов? >A: Вообще говоря, да. Во-первых, существует куча более других способов писания под mod_perl - Perl-SSI, Perl*Handlers, логика работы которых сильно отличается от CGI. Если же мы говорим о тех скриптах, которые выполняются через Apache::Registry, то есть следующие различия: 1. Hельзя использовать my-переменные уровня файла. То есть использовать можно, но результат будет ну очень странный. Дело в том, что с точки зрения перла, mod_perl-овый скрипт это не файл, а тело процедуры. Поэтому использование в нем my переменных, которые потом пользуются из вложенных процедур, приводит к возникновению closure и всему, что из этого следует. Я лично исполюзую следующую технику: use CGI; use DBI; use strict; use что-там-еще-надо &main; sub main { my $cgi=new CGI; .... } sub some_more_sub { ... } При таким образом написанном скрипте я уверен что lexical scoring будет вести себя одинаково и в CGI и в mod_perl. 2. Скрипты живут долго. Поэтому мусор за собой надо чистить аккуратно. 3. Тебе доступен объект Apache::Request, который содержит уйму интересной информации; в частности, из него можно вытащить пароль при basic authentication. 4. Теоретически, у тебя есть куда больше способов повлиять на поведение Apache в процессе обработки твоего запроса, чем из CGI. 5. Если ты используешь самописные модули, то при их редактировании придется апач перестартовывать (apachectl graceful) - поскольку крайне сложно (и долго) проверять все зависимости, Apache::Registry проверяет только момент изменения самого исполняемого им скрипта, а модули, используемые в качестве Perl*Handler, не проверяются вообще. Если в конфигурации Апача сказано PerlFreshRestart On, то достаточно его об этом попросить вежливо (SIGUSR1 AKA apachectl graceful или SIGHUP AKA apachectl restart), но за отработкой этой директивы при наличии сложных модулей замечены проблемы. Если она Off, то придётся положить и поднять (apachectl stop; apachectl start). Существует модуль Apache:StatINC, который следит за изменениями модулей и перегружает их по мере изменения. Hо есть подозрение, что он не надёжнее PerlFresRestart. При изменении модулей остерегайтесь эффекта частичного срабатывания - некоторые запросы обрабатываются еще старой версией модуля, а некоторые - уже новой. Это происходит оттого, что модуль грузится отдельно каждым экземпляром Apache, скорее всего, только при первом обращении к использующему его скрипту, а потому часть экземпляров "запомнила" старый, а к остальным попал уже "новый". --- * Origin: (2:5020/794.13) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.cgi.perl/259939d652263.html, оценка из 5, голосов 10
|