Запуск Perl-скриптов

Материал из wiki.owlhost.net
Перейти к: навигация, поиск


Запуск Perl-скриптов

ТЕОРИЯ - Как работает Perl-интерпретатор и шлюз CGI

Для того чтобы понять, как же заставить заработать Perl-скрипт, и разобраться в самых распространенных ошибках при установке, необходимо для начала понимать, каким образом запускает и работает Perl-скрипт

Perl-скрипты являются в общем случае некомпилируемыми в исполняемый файл, то есть интерпретируемые Perl-интерпретатором каждый раз при запуска Не будем пока касаться устройства механизма компиляции, а также вопроса как оптимизировать запуск Perl-скриптов На данном этапе важно понять как именно они запускаются программистом или пользователем Распространено мнение, что Perl-скрипт должен начинаться с так называемой shebang-конструкции, в которой написано что-то вроде #!/usr/bin/perl для Unix, и даже что-то типа #!Perl для Windows На самом деле данная строчка не является Perl-кодов и что немаловажно, вообще не имеет никакого отношению к языку Perl, а только относится к конкретному файлу Итак мы выяснили, что shebang-строка (Будем далее ее называть также по-умному не имеет прямого отношения в Perl Как же тогда запускать Perl-скрипт? Да очень просто, вызвав команду /usr/bin/perl /path/to/script.pl или просто perl /path/to/script.pl Если вы работаете под Windows, и вас интерпретатор занесен в переменную окружения Path, то вызвать Perl-скрипты можно аналогично, только не забыв подставить букву диска в пути к Perl-скрипту

Так для чего же нужна тогда shabang-строка, и почему она считает необязательной, если ни один CGI-скрипт, написанный на Perl, без нее не заработает? На самом деле все дело в правах доступа по UNIX Дело в том, что в отличие от Windows, файл имеет разрешение не только на чтение или запись, но и на выполнение его тем или иным пользователем При установке прав пользователя на файл, привилегия выполнения это третье число, то есть к примеру 0755 означает все права для владельца, и чтение и выполнение для группы пользователя и всех остальных пользователей То есть в UNIX имеется возможность попробовать запустить любой файл, если на это имеется соответствующее разрешение, причем расширения файла может и не быть вообще Можно попробовать запустить любой файл командой ./filename из директории с данным файлом Если файл оказывается двоичным исполняемым файлом, то он попросту запускается Но если файл оказывается текстовым, то ничего страшного тоже не происходит, и тогда операционная система начинает искать shebang-конструкцию, и если находит ее то запускает указанный там двоичный файл, и передает ему данный файл в качестве аргумента Таким образом, для Perl строка с shebang-конструкцией является ТОЛЬКО комментарием, а вот для операционной системы дает возможность узнать интерпретатор для данного файла

Такой подход дает возможность использовать интерпретируемые программы в UNIX наравне с компилируемыми В сервере Apache на самом CGI-скрипты не являются поддерживаемыми сами по себе, для их работы требуется модуль cgi_module, который добавляет тип данных cgi-скрипт И если какой-то файл имеет данный тип, то Apache формирует переменные окружения и просто запускает данный CGI-скрипт в операционную системе

В Apache для Windows такая система работала бы чуть хуже Как уже было сказано, после того как Apache определяет, что данный файл является CGI-скриптом, он передает его на запуск операционной системе Но Windows умеет исполнять только двоичные исполняемые файлы, и поэтому не знает что делать с shebang-конструкцией По этой причине в Apache под Windows была добавлена возможность распознавания с помощью Apache самой shebang-строки в CGI-скрипте, и уже вызов интерпретатора с данным аргументом в виде данного файла Такой подход дал возможность сделать Apache совместимым в UNIX и Windows Кстати поведение модуля cgi_module в Apache под Windows тоже регулируется Дело в том что Windows в принципе тоже умеет запускать неисполняемые файлы, определяя их интерпретатор по расширению, список которых хранится в реестре Для переключения данной настройки в режим реестра Windows используется опция ScriptInterpreterSource registry, для переключения обратно данная директива удаляется

Таким образом мы выяснили, как запускаются CGI-скрипты в Apache и для чего нужна shebang-строка Заметим, что права доступа на CGI-скрипт должны быть такими, чтобы пользователь Apache, который обычно называется www-data, мог бы запускать данный CGI-скрипт, при этом установка 777 всегда должна давать такую возможность Однако на некоторых хостингах права 777 выставлять запрещено и при этом возникает ошибка, такое поведения сделано с целью повышения безопасности, но оно никак не противоречит вышеуказанной схеме, просто обычно устанавливается модифицированный модуль cgi_module, который отказывается запускать CGI-скрипты с большими правами Обычно для запуска CGI-скриптов требуется определенное расширение, которые будет связано с ними Поэтому для запуска CGI-скриптов им либо придают определенное расширения, либо устанавливают их обработчиками для заданных файлов, в результате чего CGI-скрипт, выставленный в качестве обработчика запускается автоматически при вызове заданного файла, хотя при прямом вызове он может и не работать Важно не путать между собой директивы AddType cgi-script .ext для установки расширения CGI-скриптов, директиву Options +ExecCGI для разрешение выполнения CGI-скриптов в данной директории, а также директиву Action для установки данного CGI-скрипта в качестве обработчика для определенного типа файлов, установленного с помощью отдельного AddType для этого типа В данной схеме разрешено множественное перенаправление, как по shebang-конструкциям, так и по типам файлов для CGI-скриптов Например если указанный в shebang-конструкции файла также оказывается интерпретируемым файлом со своей shebang-конструкцией, то он будет запущен по цепочке с последовательной передачей файлов как аргументов соответствующим интерпретаторам, но при этом необходимо чтобы все файлы были CGI-скриптами с shebang-конструкциями

Аналогично можно использовать произвольный CGI-скрипт для обработчика другим файлом, правда необходимо сделать всю цепочку из файлов с расширениями CGI-скрипта, либо использовать AddHandler заместо AddType При этом корневые исполняемые файлы, типа /usr/bin/perl должны быть объявлены в цепочке в основном конфигурационном файле Apache под названием httpd.conf, так как внутри .htaccess файлов нет доступа ко всей файловой системе

Практика - Установка Perl-скрипта и настройка web-сервера для запуска CGI-скриптов

Теперь можно применить полученные знания на практике, в частности для конфигурации Apache и запуска своих Perl-скриптов в CGI-режиме Для удобства будем рассматривать Linux-сервер, так как запускать и тестировать свои Perl-скрипты обычно приходится на настоящем хостинге Даже в том случае, если у вас имеется свой сервер или вы настраиваете Apache под Windows, данный материал будет вам полезен, потому что как было указано ранее настройка Apache достаточно схожа Для начала необходимо удостоверится в наличии Perl и соответствующих модулей к нему Частой причиной неработоспособности Perl-скриптов является именно отсутствие нужных модулей Для того, чтобы обобщить настройку Perl под Linux и windows, при установке Perl по Windows воспользуемся следующим правилом - структура каталогов должна быть примерно такая же, как и на системе Linux (Аналогичную структуру предоставляет Denwer), то есть исполняемый файл perl должен быть в папке /usr/local/bin, а модули в /usr/local/lib Также важно добавить путь к исполняемому файлу Perl в переменную окружения Path Для удобства и дополнительной совместимости с linux, также лучше держать всю структуру unix-подобных каталогов в корне диска или на виртуальном диске, чтобы не использовать букву диска в путях Учитывая, что прямой / и обратный \ слеш во многих конфигурационных файлах идентичны, такой подход даст сильную схожеть с linux Чтобы установить Perl под Windows, необходимо скачать ActivePerl с сайта http://www.activestate.com/activeperl/ и установить в заданных корневой каталог, сохраняя структуру дерева папок Также надо помнить, что не во всех операционных системах типа *NIX пути будут в точности такими же, часто встречаются пути и без каталога /local/, то есть просто /usr/bin и /usr/lib, а также /etc для конфигурационных файлов

Установка модулей под Windows осуществляется с помощью программы PPM, которая имеет графический интерфейс и умеет сама скачивать и компилировать модули, а также устанавливать их в нужную директорию Для увеличения списка возможных модулей, нужно выбрать репозиторий, список которых можно получить в интернете Также при установке важно выбрать правильную папку для хранения модулей Perl, так как будет предложено несколько папок со схожими путями, при этом необходимо выбрать ту, которая не имеет имени диска Если таких папок несколько, то нужно выбрать ту которая имеет путь оканчивающийся на site/lib, а если же во всех папках указан путь диска, это свидетельствует о неправильной настройке Perl Для установки модулей под Linux необходимо компилировать их вручную, при этом обычно используется программа-конфигуратор configure, в которой определяется путь к папке с модулями Perl, и происходит соответствующая настройка Для некоторых дистрибутивов Linux существуют скомпилированные модули, аналогичные модулям Windows, их можно получить и автоматически настроить через установщик apt-get и ему подобные Важно помнить, что часть модулей под Windows имеют характерную особенность, а именно скомпилированные в dll-файл компоненты данного модуля, и загружаемые через bootstrap Именно поэтому достаточно сложные модули нельзя просто копировать не только между разными системами, но и разными папками, так как dll-файлы должны лежать в четко определенном месте Также в Perl имеется возможность для заданного Perl-скрипта указать путь к библиотекам, это можно сделать с помощью прагмы use lib 'path/to/library', указав относительный или абсолютный путь Если таким образом загружается библиотека со скомпилированными компонентами, то dll-файлы можно лежать в папке /auto относительно пути к модулю Надо помнить, что если просто перенести или скопировать модуль с динамическими компонентами в пользовательскую папку, указываемую в прагме lib, то такая библиотека может и не заработать, даже если перенести динамические компоненты в папку /auto - поэтому если очень нужно именно такое использование модуля, то нужно скомпилировать его именно для заданного пути

Зная вышесказанное, можно запускать Perl-скрипты по windows и под linux В linux благодаря shebang-конструкции с ними можно работать с ними наравне с обычными программами, а в windows можно связать определенное расширение (Например .pl) с интерпретатором Perl и работать с программами также просто Из теоретической справки выше нам известно, что Apache работает с Perl-программами через CGI, причем работает с ними наравне с обычными скомпилированными исполняемыми программами, поэтому дальнейшая работа сводится в настройке Apache для работы с внешними программами через CGI-интерфейс В первую очередь необходимо проверить наличие модуля cgi_module для Apache Он сопоставляет файлам с заданным расширением прямой запуск данных программ, такими расширениями обычно являются .cgi, .pl и .exe, при этом данные файлы могут быть как скомпилированными исполняемыми программами, а могут содержать shebang-конструкцию Для совместимости с shebang-конструкциями, в windows необходимо убрать директиву ScriptInterpreterSource registry, чтобы Apache мог работать с данными файлами в точности как в linux Для запуска CGI-скриптов под linux, необходимо указать верные права доступа, необходимые для того чтобы внешний пользователь (Обычно www-data от Apache) мог выполнять данную CGI-программу Главное чтобы права доступа были равны или больше чем необходимые, в таком случае запуск будет проходить без проблем Однако на некоторых хостингах установка высоких прав приводит в ошибке (Что сделано по соображениям безопасности), однако это не является истинным поведением, а происходит за счет специфического (Переделанного) модуля cgi_module, который проверяет нужные права доступа, похожим образом работают модули, которые запускают CGI-скрипты от имени пользователя, которому они принадлежат, однако все эти схемы не являются общеупотребительными Далее при запуске любого CGI-скрипта, Apache формирует переменные окружения и передает POST-данные на STDIN в программу, ожидает ее выполнения, считывает информацию с STDOUT и выводит ее При этом формированием HTTP-заголовков занимается CGI-скрипт, и в случае возникновения какой-то ошибки в Perl-скрипте, Apache просто выдает 500 ошибку - Inertal Server Error, не вдаваясь в причины ее появления В любом случае для Apache, любая CGI-программа является закрытой внешней программой, и Apache не знает о причинах ошибки внутри программы, он лишь проверяет заголовки и выводит информацию пользователю


Если вы используете Linux\Unix, то скорее всего perl у вас уже установлен. Проверить это проще простого: зайдите в консоль и наберите в ней «perl»(+перевод строки, естественно). Если он уже установлен, то консоль будет ожидать дальнейший ввод — код вашего перл-скрипта. Для выхода из этого режима нажмите Ctrl+C — прерывание, либо нажмите Ctrl+D — указание perlу конца кода, он его выполнит(а чего бы и не выполнить пустой запрос :) ) и вы вернётесь в консоль.

Кстати, зайдите снова в perl и наберите банальное print «Hello World!» после чего нажмите Ctrl+D. Если вы не опечатались, perl выведет «Hello World!» прямо на STDOUT, а именно в консоль. Это рекомендуют сделать первым практически все учебники по перл.

Как использовать скрипты Perl?

Необходимо в качестве первой строки скрипта указать:

  1. !/usr/local/bin/perl

Файл скрипта должен иметь атрибуты доступа 711. Выставить их можно при помощи FTP-клиента или используя команду chmod 711 script.pl (где script.pl - Ваш скрипт). Внимание: скрипт должен находиться в директории cgi-bin. По умолчанию, вызов скриптов возможен только из этой директории.

[править] Запуск

Нет смысла учить язык, если нету способа по-практиковаться. Мы уже видели один способ запуска perl-скрипта:

root[~]# perl print "HW!" HW!root[~]#

Хороший способ для проверки синтаксиса(взбрела в голову конструкция и интересно поймёт ли perl). Однако, для написания как-либо больших программ или проектов этот способ не годится. Приятно было бы писать в файл и исполнять его. Для этого нужно создать файл с расширением pl (можно и без него, но тогда у Windows возникнут вопросы по поводу идентификации программы-исполнителя этого файла), в него записать свой код. Начать код нужно с #!/usr/bin/perl (опять же можно и без этого, но тогда уже у Unix возникнут проблемы с идентификацией) — этот комментарий указывает операционке через какой файл нужно будет запускать нашу программу.

Кстати, комментарии в perl пишутся в Unix-style — ставится знак # и до конца строки можно писать всё, что придёт в голову(хоть анекдоты, как это часто делают perl-программисты) — perl это просто отбросит…

Запускать файл, оформленный подобным образом можно обычным двойным кликом. При таком запуске будет вылазить персональная для нашего скрипта консоль и по окончании работы скрипта закрываться, что вызывает некоторые трудности:

   Подобный запуск для людей, привыкших к графике и пугающихся консоли, выглядит эстетически неприемлимым. Мы уберём консоль, когда научимся писать перл-скрипты с использованием графического интерфейса.
   Вывод как шёл на консоль, так и идёт… Поэтому, если мы выводим результат работы скрипта обычным print’ом, то он выведется на консоль, которая закроется сразу же по окончании работы скрипта. Это легко обходится обычным запросом на ввод в конце нашего кода, но, согласитесь, момент тоже неприятный…
   Теряем всю отладочную информацию. А она стоит немало… Вообще одна из расшифровок названия PERL — Patalogically Eclectic Rubbish Lister (патологический эклектичный распечатывальщик мусора). Мусор мусором, а информации, выводимой при поломке в большинстве случаев хватает для починки (номер строки, где умер скрипт, чего не хватает…)

Итак, не зря я привёл столько доводов против данного способа запуска: данный способ подходит только для запуска конечного продукта. Для отладки лучше всего подходит 3-ий способ:

root[~]# perl code.pl

Кстати, можно и не писать «perl», если вы не забыли написать в начале кода «#!/usr/bin/perl». Правда, при использовании Unix вам потребуется предварить название файла с вашим кодом адресом папки, в которой лежит скрипт. К примеру, «./code.pl».


[править] Пару слов о типах.

Как и в любом языке (кроме, пожалуй, кодов процессора), в перл данные не просто свалены в кучу, а для удобного использования разбиты на типы. Люди, уже программировавшие на языках C\C++ или Pascal\Delphi сразу вспомнят про int(integer), char, string и будут не правы.

Для всего выше перечисленного в перл есть эквивалент — скаляр, он же — 1ый тип данных. По сути, скаляр — это «элемент», и не важно какого множества: чисел, символов, строк, ссылок… Главное, что он один! Для того, чтобы создать скаляр нам не нужно его как-то особенно объявлять, просто используем: $a=12; Значок $ даёт понять перлу, что это скаляр, а не что либо другое. Для примера, объявим несколько скаляров и проделаем с ними несколько стандартных операций (а ля if, while, for).

В догонку: комментарии в перл начинаются с символа #.

  1. !/usr/bin/perl

$a = 12345; $b = 12345.67; $c = .23E-10; $hex = 0xffff; # шестнадцатеричная запись $oct = 0377; # восьмеричная запись $d = 1_234_567_890; # то же самое, что и 1234567890 print $a.$b; # Выведет "1234512345.67" print '=' x 79, "\n"; # Выведет символ "=" 79 раз, после чего символ "\n" - перевод строки $rub = "$a рублей\n"; print $rub; # Выведет "12345 рублей", перевод строки $a -= 12300; # теперь $a равен 45ти if($a){ # $a не 0 и не "0", и не "", и не undef, то есть - истина!

   print "Привет из 1ого if'а"

} while($a){ # пока $a не станет равен 0 (в результате $a--)

   print --$a

} print "привет из unless'а" unless $a; # unless - это if not.

  1. Сама конструкция может быть записана как unless($a){print "привет из unless'а"},
  2. но это не красиво :)

Что нового мы могли увидеть в этом коде? Для тех, кто ещё не знаком с конкатенацией(сложением строк) мог быть непонятен оператор . (точка). Он складывает строки(склеивает), оператор умножение строки на число, думаю, так же мог создать несколько вопросов. Оператор «x» берёт слева строку и повторяет её указанное справа число раз. Как можно уже было заметить, все операции в перл заканчиваются точкой с запятой. Однако, точка с запятой необязательна в некоторых случаях:

   Если операция последняя в блоке(блок — всё то, что стоит между «{» и «}»)
   Если операция последняя в файле

Так же можно было заметить, что 1-ый комментарий нам ничего не объяснял… Задачей его было объяснить операционной системе через что запускать данный файл. В данном случае мы запускаем через исполняемый файл, находящийся по адресу /usr/bin/perl. Эту строчку можно и не писать, но тогда запускать файл придётся из консоли с прямым указанием на программу, которая будет интерпретировать наш код, то есть так:

Unix-way:

~$ perl example1.pl

в случае, если наш код сохранён в файл ~/example1.pl или же, при наличии первого комментария можно запускать так:

~$ ./example1.pl

или даже 2мя кликами по файлу(в графической оболочке), но для данного кода смысла в этом мало — всё выполнится и сразу исчезнет.

В Windows всё сделано иначе, а именно через расширение файла (.pl), поэтому можно опять же дважды кликнуть или же пойти в консоль и набрать там

> perl example1.pl

или даже

> example1.pl

и увидеть работу нашего первого скрипта.

Кстати, если вы ещё не заметили, в переменную $a мы клали число, а пользовались при конкатенации уже строкой. Во время if’a $a вообще становилась логическим значением… И это всё «бесплатно» — без всяческих конвертов и явных преобразований типов. Перл сам знал что нам надо и конвертировал переменную в тот тип, который нам нужен в данный момент. Вот такой вот умный зверь! :)

Но для того, чтобы он нас понимал, мы должны так же понимать и его: к примеру, когда мы преобразовываем скаляр в логическое выражение, мы должны понимать, что всё правда(истина), кроме пустой строки, нуля, строки «0″ и специального значения undef — не определён. Создать скаляр, значения undef проще простого: undef $a или $a = undef.

Ok. Теперь у нас есть возможность пользоваться переменными — элементами, но если нам надо использовать множество таких… Иначе говоря массив элементов. Для этих целей в перл есть тип данных «массив». Его опять же никак не надо описывать… просто используй! @a = (0,1,2,3,4); опять же символ @ здесь непросто для красоты, а указывает на то, что это массив! В данном примере мы присвоили первым 5ти элементам массива цифры от 0 до 4. И опять несколько примеров:

  1. !/usr/bin/perl

@a = 0..9; # забили первые 10 элементов массива цифрами от 0 до 9 print $a[2]; # напечатали 2ой элемент массива. Почему здесь $ а не @?

  1. всё логично: используем мы не массив, а элемент, пусть даже массива...

print @a[2..6]; # а вот здесь как раз @, потому как и печатаем мы не элемент,

  1. а подмассив (кусок массива, слайс) со 2ого по 6ой элемент

print for @a; # Ещё один классный пример того, как перл понимает на с полу слова :)

  1. если для кого не очевидно, что здесь происходит - объясняю:
  2. для каждого элемента массива @a напечатать его.

while(@a){ # пока массив не пуст

   print pop @a # напечатать то, что выпихнул pop из конца массива

} # так как pop уменьшает массив, то и из цикла мы выйдем

3-ий и последний тип данных — хеш(hash), произносится как «хэш». Так же его можно назвать ассоциативным массивом. Мы его пока можем представлять, как некий массив, где элемент мы получаем не по числу — номеру элемента, а по строке — ключу хеша.

Объявляется хеш так: %h = (color => ‘red’, width => ’10px’, height => ’100px’); процент указывает на то, что это хеш. В него мы передаём массив из 6ти элементов, каждый чётный воспринимается как значение, а нечётный — как ключ. То есть по ключу color мы получим значение red. Может показаться странной конструкция color => ‘red’. Мы могли это так же записать как «color»,’red’. Правда у => есть ещё пара козырей: он сначала выполнит то, что слева(если это команда), после этого заменит все переменные их значениями, как это делают двойные кавычки. К слову: print '@a'; # выведет "@a" print "@a"; # выведет содержимое массива @a

Пара примеров с хешами:

  1. !/usr/bin/perl

%h = (

   color => 'red',
   width => '10px',
   height => '100px'

); print $h{'color'}; # и опять скаляр, только скобочки уже

  1. не квадратные(как у обычного массива), а фигурные

print "\n$_ => ",$h{$_} for keys %h;

  1. Для неподготовленного человека это может показаться просто кракозяброй,
  2. Но мы уже кое-что знаем и можем понять смысл этой команды за исключением 2х моментов.
  3. 1. keys - функция, возвращающая массив ключей поданного на вход хеша
  4. 2. скаляр $_ - это переменная "по умолчанию". Проще говоря, это то, о чём сейчас речь,
  5. в данном случае речь идёт об элементе массива ключей(на каждом шаге цикла о разном).
  6. $_ - первая специальная переменная из множества, заложенных в перл.


[править] Вызов сgi-скрипта в системе unix

Если вы поместили ваш скрипт в каталог cgi-bin и сделали его выполнимым, то поль­зователь может вызвать скрипт, непосредственно используя URL. Однако необходи­мо выполнить несколько шагов. В первую очередь, в начало скрипта необходимо по­местить строку, которая идентифицирует файл как программу на языке Perl :

           #!/usr/bin/perl   

Примечание: Вы должны будете указать в этой строке путь, зависящий

от того, где установлен Perl на вашей системе.

Далее необходимо сделать скрипт выполнимым, используя команду chmod :

chmod +x your-srcipt

Если директория отлична от установленной по умолчанию, то в этой директории необходимо создать файл .htaccess со следующим содержанием: Options ExecCGI.