Разделы:

Главная

О проекте

Загрузки

Документация:

Linux

BSD

Другие Unix

Программинг

HTML, XML...

Сервера

"Окна Закрой!"

MANы

 


FAQ Perl

 

Чем отличается синтаксис скриптов на UNIX и WIN платформах?

Ответ:

Юниксовый Perl плохо воспринимает досовский перевод строки - CR LF. Если открыть такой файл в vi в конце строк будут ^M. Удалить их можно, например таким скриптом:
#!/bin/bash 
install -d -m 0775 orig 
cp $1 orig/$1.orig.`date +%m-%d-%H.%M` 
sed -e "s/^M//g" $1 >oooo 
mv -f oooo $1 
Некоторые перекодировщики также умеют конвертировать концы строк.
 

А как мне проверить соответствие введенного пароля зашифрованному?

Ответ:

Первых два символа пароля соджержат шифровальный ключ. Если взяв их зашифровать проверяемый пароль, то зашифрованные строки должны совпасть. Пример:
if (crypt($entered_passwd,substr($crypted_passwd,0,2)) eq $crypted_passwd)
{ # Пароль верен } else { # Пароль не верен } 
 

Как мне получить зашифрованный пароль?

Ответ:

Стандартной функцией crypt(), например вот так:
# Calculate salt value for crypt function
@saltair= split //,"ABCDEFGHIJKLMNOPQRSTUVWXYZ
 abcedfghijklmnopqrstuvwxyz0123456789./";
sub get_salt {
srand();
$iOff = int(rand($#saltair));
$iOff2 = int(rand($#saltair));
return join("",$saltair[$iOff],$saltair[$iOff2]);
}

$crypted_passwd = crypt($plain_passwd,get_salt()); 
 

Как мне сделать аутентификацию на Перле, а не средствами веб-сервера?

Ответ:

Для того, чтобы браузер выдал запрос логина и пароля, скрипт должен выдать следующие заголовки:
print "WWW-Authenticate: Basic realm=\"что то там\"\n";
print "Status: 401 Unauthorized\n\n";
print "Ошибка авторизации!\n";
При этом "что то там" - это имя области авторизации, по правилам для области с одним именем должен всегда срабарывать один и тот же пароль. Проблема заключается в том, что ответ пользователя сидит в заголовке HTTP-запроса, в поле Authorization, которое скрипту через переменные окружения не передаётся. Для сервера Апаче эта проблема решается прописыванием в файле конфигурации следующих строк:
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_CGI_AUTHORIZATION:%1]
Всё что он делает - это добавляет в переменную окружения HTTP_CGI_AUTHORIZATION, в которую пишется содержимое HTTP заголовка Authorization, таким образом означенное поле становится доступным для анализа внутри скрипта. Формат этого поля следующий: "login:password", причём эта строка закодирована в Base64, получить эти составляющие можно так:
use MIME::Base64;
$ENV{HTTP_CGI_AUTHORIZATION} =~ s/basic\s+//i;
($REMOTE_USER,$REMOTE_PASSWD) = split(/:/,decode_base64($ENV{HTTP_
CGI_AUTHORIZATION}));
 

Я пытаюсть скриптом вывести картинку, а мне вместо нее выдается стандартная битая картинка браузера.

Ответ:

В этом есть две причины, во-первых необходимо выдавать правильные заголовки, во-вторых на некоторых веб-серверах необходимо переводить потоки ввода-вывода в бинарный режим, лучше это делать всегда. Если Вы берете файл из картинки, можете воспользоваться следующим примером:
print "Content-type: image/gif\n"; # Для JPEG будет
print "Content-length: 7256\n\n";
open (IMG1,"image.gif");
binmode IMG1;
binmode STDOUT;
print ;
close (IMG1);
Заголовок Content-length в принципе необязателен, но желателен. Он должен содержать реальный размер файла в байтах. Его можно получить воспользовавшись конструкцией -s
 

Как сделать upload картинки через форму?

Ответ:

use CGI qw/:standard/;
# Код для формы
print "Content-Type: text/html\n\n";
print < 
<'head'><'title'>file upload<'/title'><'/head'>

<'form method="post" enctype="multipart/form-data" action="upload.pl"'>
<'input type="file" name="picture"'>
<'input type="submit" name="Submit" value="Submit"'>



EOF

if(param()){&insert_image(1);}
sub insert_image
# путь к директории для закачки
$downpath = "download/";
my $in=param('picture');

# выделяем имя файла из параметра
@fname = split(/\\/,$in);
$kk = @fname;
$name = $fname[$kk-1];

open OUT, (">$downpath$name");
binmode(OUT);
# читаем входной поток и пишем в файл (файл в binmode!!!)
le(<$in>){ 
print OUT $_; 
} 
close(OUT); 

# выводим надпись о закачке файла <$name>
print "<'h2'>Upload file: $name<'/h2'>";
};
 

Где можно взять Perl?

Ответ:

На CPAN == Comprehensive Perl Archive Network. Homepage CPAN -- http://www.cpan.org/ -- там берут все, связанное с перлом. Собственно исходники новейшей версии перла берут из файла http://www.perl.com/CPAN/src/latest.tar.gz (на самом деле с www.perl.com стоит редирект на ближайший, по мнению www.perl.com, mirror).
 

Я скачал модуль Lib::Module. Как его установить?

Ответ:

Обычно модуль приходит в формате tar+gzip, типа module-0.01.tar.gz. Вам необходимо его развернуть:
gzip -dc module-0.01.tar.gz | tar xf -
и перейти в образовавшуюся директорию, например module-0.01: 
  cd module-0.01
Обычно там находятся несколько файлов. Для вас будут важными следующие:
  README    - что это за модуль
  INSTALL    - как его поставить
  Makefile.PL  - перловый скрипт для генерации Makefile
Обычно инсталляция происходит следующим образом:
  perl Makefile.PL - генерация Makefile
  make all  - сборка модуля
  make test  - тестирование модуля
  make install  - инсталляция модуля
Необходимо внимательно смотреть, не возникли ли какие ошибки во время первых трех команд. Внимание: вы должны иметь административные привелегии для инсталлирование модуля в системе (обычно как root). Но, если вы их не имеете, то можете инсталлировать модуль у себя. Для этого вам необходимо выбрать, где это будет делаться. Для примера, в $HOME/lib/perl5. Необходимо создать эти директории, если их нет:
  mkdir ~/lib
  mkdir ~/lib/perl5
Затем, при генерации Makefile для модуля, вы должны указать, где вы хотите инсталлировать модуль:
  perl Makefile prefix=$HOME
Все остальные шаги без изменений. В результате вы получите альтернативное место, где у вас будут находиться модули. Например, у меня это выглядит так:
  artur@disco:~ (681) ls -alFg ~/lib/perl5/
  total 704
  drwxr-sr-x   8 artur    staff        512 Oct 06 15:53 ./
  drwxr-sr-x   9 artur    staff       1024 Oct 08 10:50 ../
  drwxr-sr-x   4 artur    staff        512 Mar 31 1998  aix/
  drwxr-sr-x   2 artur    staff        512 Aug 06 13:40 CPAN/
  -r--r--r--   1 artur    staff     126951 Jul 24 19:37 CPAN.pm
  drwxr-sr-x   3 artur    staff        512 Mar 31 1998  man/
  drwxr-sr-x  31 artur    staff       1024 Sep 09 15:41 site_perl/
Для того, чтобы их использовать, есть несколько путей: 1. указывать при запуске perl в командной строке:
  perl -I$HOME/lib/perl5 -I$HOME/lib/perl5/site_perl script.pl
2. завести переменную шелла PERL5LIB:
  для sh (bash,zsh,ksh)
  PERL5LIB=$HOME/lib/perl5:$HOME/lib/perl5/site_perl
  export PERL5LIB
  для csh (tcsh)
  setenv PERL5LIB $HOME/lib/perl5:$HOME/lib/perl5/site_perl
3. указывать в начале скриптов дополнительные библиотеки:
  use lib "/home/you/lib/perl5";
  use lib "/home/you/lib/perl5/site_perl";
Данный случай подходит к CGI-скриптам, которые не наследуют ваших переменных окружения.
 

Как автоматизировать процесс установки библиотек и модулей?

Ответ:

Скачивание и установка вручную -- достаточно сложное занятие, требующее постоянного вмешательства с вашей стороны. Можно простым способом: сделать su (желательно), набрать perl -MCPAN -e shell. Если это первый запуск модуля CPAN, вам задатут серию вопросов на тему URL вашего любимого зеркала CPAN. После этого все просто: если вы знаете название модуля или библиотеки, то набираете, скажем, install Net::NNTP. Тогда этот модуль (для работы с NNTP) сам ищется на CPAN, сам скачивается, компилируется, устанавливается. Все, поставили, можно выходить и использовать вновь установленный модуль. Если название точно не известно, то набираем там же help и испльзуем различные команды поиска типа i NNTP.
 

Где взять стандартную документацию про такое-то свойство Perl?

Ответ:

Перл приходит с полным набором документации и набором программ для переведения в разные форматы. Обычно для подробного ознакомления с некоторой особенностью перла пишут "perldoc perlсвойство" или "man perlсвойство". Базовый набор "свойств" таков:
     Основы          perldata, perlvar, perlsyn, perlop, perlsub
     Запуск          perlrun, perldebug
     Функции         perlfunc
     Objects         perlref, perlmod, perlobj, perltie
     Data Structures perlref, perllol, perldsc
     Modules         perlmod, perlmodlib, perlsub
     Regexps         perlre, perlfunc, perlop, perllocale
     Moving to perl5 perltrap, perl
     Linking w/C     perlxstut, perlxs, perlcall, perlguts, perlembed
     Various         http://www.perl.com/CPAN/doc/FMTEYEWTK/index.html
                     (not a man-page but still useful)


     perl          О перле вообще
     perldelta     Что нового в последней версии перла
     perlfaq       FAQ
     perltoc       Подробное оглавление ко всей документации
     perldata      Типы данных
     perlsyn       Синтаксис языка
     perlop        Арифметические, логические, строковые 
                     операции и их приоритет
     perlre        Регулярные выражения (обработка текста и поиск)
     perlrun       Опции командной строки
     perlfunc      Встроенные функции
     perlvar       Специальные переменные
     perlsub       Как писать свои функции (процедуры)
     perlmod       Устройство и принцип работы модулей
     perlmodlib    Модули: создание собственных библиотек
     perlmodinstall Поиск и установка модулей и библиотек на CPAN
     perlform      "Форматы", или шаблоны для выводимых данных
     perllocale    Поддержка интернационализации
     perlref       Ccылки и указатели на данные
     perldsc       Введение в структурные типы данных
     perllol       Структуры данных: массивы и списки 
     perltoot      Введение в объектно-ориентированное
                     программирование
     perlobj       Объекты в перле
     perltie       Связь объектов с обыкновенными переменными
     perlbot       Perl OO tricks and examples
     perlipc       Связь между процессами: pipes, sockets, 
                     сигналы и др.
     perldebug     Отладка программ
     perldiag      Сообщения об ошибках
     perlsec       Вопросы безопасности
     F
     perltrap      Возможные грабли и ловушки
     perlport      Как писать портабельные программы
     perlstyle     Стиль программирования на перле
     perlpod       Формат стандартной документации и документация, 
                     встраиваемая в исходные тексты программ
     perlbook      О книгах про перл

     --- (для совсем крутых) ---
     
     perlembed     Способы внедрения перл-программ в программы на C/C++
     perlapio      Собственный API, использумый в исходниках перла
     perlxs        XS -- программирование перловских библиотек,
                     используемых вместе с библиотеками на C
     perlxstut     Учебник по XS
     perlguts      Внутренние функции перла для разработчиков
     perlcall      Соглашения о вызове перловских функций из C
     perlhist      История и полный список всех версий перла
 

Где взять описание модуля Lib::Module?

Ответ:

Формат стандартной документации по перлу (pod) обладает возможностью встраивания прямо в тексты программ, а программа perldoc -- возможностью извлечения этой документации. Поэтому, чтобы получить документацию по модулю Math::Trig, просто наберите perldoc Math::Trig -- perldoc найдет этот модуль и покажет документацию из него. Если модуль не является частью какой-то библиотеки, а существует сам по себе, например, CGI.pm тогда просто perldoc CGI.pm или даже perldoc CGI. NB: программа perldoc не очень расторопна, поэтому при установке перла под UNIX производится создание manpages для всех модулей, так что man CGI или man Math::Trig покажет быстрее, чем perldoc.
 

Как пользоваться функцией pack (getpwuid, dmbopen)?

Ответ:

man perlfunc или "perldoc -f имя_функции | pod2text" Пара примеров для unpack: Определение типа изображения и его размеров:
sub get_image_spec {
        # Возвращает ($Тип_изображения, $ширина, $высота)
        my $buf = $_[0];
        my ($type, $width, $height);
        if (unpack("n", $buf) == 0xffd8) {
                return ('jpeg', 0, 0); # Про jpeg я пока не знаю как
                # определить его размеры
        } elsif (unpack("A4", $buf) eq "GIF8") {
                my ($type, $width, $height) = unpack("A6 v v", $buf);
                return ('gif', $width, $height);
        }
}

read(STDIN, $buf, 120);

print join (", ", get_image_spec($buf));
 

Как узнать размер файла (дату создания, атрибуты, разрешения на доступ)?

Ответ:

С помощью так называемых файловых тестов, которые имеют вид (-тест "имя файла"), например:
    (-s "file.txt") размер файла
    -e              существует ли файл
    -w              доступен ли на запись
    -M              количество дней со дня модификации
    -t              является ли терминалом
 

Как отправить почту из скрипта на Perl?

Ответ:

Способ для Unix
        ---- 
        open MAIL, '|/path/to/your/sendmail -t'; # Pipe к sendmail
        print MAIL "From: mailrobot@my.host\n",
                   "To: webmaster@my.host\n",
                   "Subject: Wow! I got some mail for you!!!\n\n",
                    $message;
        close MAIL;
        -----
Подробности: man sendmail, http://www.sendmail.org У меня не Unix! Что делать? Вероятно, Вам поможет модуль Net::SMTP
 

Как написать модуль?

Ответ:

Простейший случай: Сам модуль представляет из себя файл с именем MyModule.pm следуещего содержания:
package MyModule;
require Exporter;

@ISA = qw(Exporter);

@EXPORT = qw(идентификаторы для экспорта: 
подпрограммы, имена переменных и
пр.);
# Теперь после того, как вы напишите 
#use MyModule в своей программе, у вас все 
# упомянутые здесь идентификаторы станут видны.
# Этот метод не рекомендуется,
# так как вы "засоряете" именное пространство программы.

# И/или
@EXPORT_OK = qw(идентификаторы для экспорта: 
#подпрограммы, имена переменных и
пр.);
# Идентификаторы, прописанные здесь будут видны
# в Вашей пргорамме как
# MyModule::Идентификатор (подпрограммы) или 
#$MyModule::Идетификатор
# (переменные)
# Или, Вы можете написать use MyModule 
#qw(Ид1 Ид2 $Ид3); и все будет как в
# первом случае. Это рекомендуемый вариант.

... ваши подпрограммы и пр ....

1; # Обязательно
# конец МойМодуль

Программа, его используящая: 
use MyModule qw(...);
# Ну и далеее
Подробности смотрите в perlmod(1), Exporter(3pm), Camel Book
 

Как получить доступ к n-му сиволу строки?

Ответ:

Надо использовать функцию substr. Например, получить 15й символ из строки $string:
       $char = ;
        Установить 15й символ строки $string:
         = 'A';
   Можно даже использовать болле чем односимвольные последовательности:

        $ss = ;

         = 'Хо-Хо';
		 
 

Под какие платформы существует Perl?

Ответ:

perl 5 - под практически все виды UNIX-систем (Linux, FreeBSD, SunOS,..), DOS (защищенный режим, i386 и выше), Windows 9x/NT, OS/2, VAX VMS, Novell Netware, Amiga.
 

А где взять компилятор?

Ответ:

Пока полноценных компиляторов не существует - скрипты выполняются и распространяются в виде исходников. Hечто, заявленное, как компилятор, и подходящее только к Activestate-перлу для w32, лежит на www.activestate.com
 

Как сделать то-то? Может, уже есть готовая библиотека?

Ответ:

http://www.perl.com/CPAN/ , http://search.cpan.org/ CPAN - огромное, отсортированное собрание всех дополнительных модулей к perl, не включенных в поставку. Собраны все версии модулей. Рядом с ними лежат readme. Скачиваете, и устанавливаете. В 90% случаев то, что вы пытаетесь сделать, уже кто-то сделал и выложил на CPAN.
 

Где взять скриптов готовых, побольше?

Ответ:

Здесь много скриптов и ссылок на них!
 

Какую книгу для начинающих посоветуете?

Ответ:

Llama Book, она же "Изучаем перл" в русском издании. С ламой на обложке. А также "Perl Специальный справочник" Стивена Холзнера. Все эти книги можно посмотреть на нашем сайте здесь.
 

Как прикрутить perl к винде, чтобы можно было скрипты выполнять локально?

Ответ:

http://www.activestate.com/, download perl. Устанавливаете, и запускаете:
perl myscript.pl
 

У меня перл от Activestate, как мне поставить такой-то модуль?

Ответ:

www.activestate.com/packages/zips/ Hаходите нужный архив, скачиваете, читаете readme. Если нужного модуля нет - ставите MS Visual C, и мучаетесь, мучаетесь..
 

А из браузера как смотреть на вывод скрипта? Почему-то показывается исходник.

Ответ:

Потому что между браузером и perl должен стоять сервер, который и запускает скрипт на выполнение, отдавая результат браузеру. Сервер не обязательно подразумевает под собой отдельный компьютер - вы можете поставить себе программу, и обращаться к ней через браузер, наблюдая за работой скриптов. Вариантов масса:
Personal Web Server из поставки Win9x
Sambar, http://www.sambar.com/
Apache-W32, http://www.apache.org/
Устанавливаете сервер, и либо указываете в настройках сервера ассоциацию на файлы cgi и pl - запуск perl.exe, либо устанавливаете такую ассоциацию на эти файлы в windows (dbl click в windows explorer AKA проводник).
 

А что это за закорючки такие в скрипте - s/^[^\w]{1,3}(\d+)/$1/

Ответ:

Это регулярные выражения, одна из мощнейших возможностей perl. Средства поиска и замены подстрок в строках
 

Как ими пользоваться?

Ответ:

Этому учатся всю жизнь. Даже целая книга есть - "Mastering regular expressions". Также следует прочесть perldoc perlre А начать можно со следующего:
      // - поиск
    s/// - поиск и замена
   tr/// - трансляция
   Если мы хотим узнать, нет ли в строке 
   $_ подстроки 'my', мы пишем:
   /my/;
   Если мы имеем дело не с переменной по 
   умолчанию, а с любой другой,   пишем:
   $str=~/my/;
   Если мы хотим заменить в строке подстроку 
   tree на root, используем   поиск и замену:
   $str=~s/tree/root/;
В конце выражения могут стоять опции g, i и т.п. g означает проводить замену не 1 раз, а по всей подстроке. i означает не учитывать регистр символов. В подстроке для поиска можно использовать управляющие символы. Есть два вида управляющих символов - мета-символы, обозначающие какой-то символ из набора букв, цифр, и т.п., и мета-символы, управляющие количеством. Hапример, \d в подстроке обозначает любую цифру, \w - любую букву, \s - пробел, . - любой символ. Стоящая после мета-символа * означает, что предыдущий символ может повторяться 0 или более раз. + означает повторение 1 или более раз. То есть, строка вида
   $str=~s/\s\d+\s/\s1\s/g;
означает "заменить все числа в строке $str, отделенные пробелами с двух сторон, на цифру 1, отделенную пробелами". Более подробное описание регулярных выражений, список управляющих символов и других возможностей смотрите в документации
 

Как не учитывать регистр в русском тексте? С английским регекспы с ключом i работают, а с русским - нет.

Ответ:

Hа Linux-е это делается так:
    use locale;
    use POSIX qw (locale_h);
    setlocale(LC_CTYPE, 'ru_RU.KOI8-R');
(можно еще выставить переменную окружения export LANG=ru_RU.KOI8-R тогда будет достаточно вызова use locale; в Perl-скрипте) Под Windows это делается так:
    use locale;
    use POSIX qw (locale_h);
    setlocale(LC_CTYPE, "Russian_Russia.1251"); # или "Russian_Russia.866"
С трансляцией АКА tr/XX/xx/ даже не используя use locale; можно так сделать:
    tr/\xB3\xE0-\xFF/\xA3\xC0-\xDF/;            # для KOI8-r

или

    tr/\xA8\xC0-\xDF/\xB8\xE0-\xFF/;            # для Windows-1251

или

    tr/\xF0\x80-\x9F/\xF1\xA0-\xAF\xE0-\xEF/;   # для CP-866
 

Как работать из perl с базами данных?

Ответ:

DBI. Это унифицированный программный интерфейс, придуманный для того, чтобы с разными базами можно было работать одинаково (за исключением, конечно, специфики самих SQL-запросов). Устанавливаете модуль DBI, ищете и устанавливаете DBD - драйвер-связку между DBI и нужной вам базой. Orcale, MySQL, Postgres и куча других СУБД поддерживаются DBI+DBD. Читаете perldoc DBI.
 

Хочу прочитать список файлов в каталоге, но почему-то не работает или глючит. Делаю так: @files=<*>;

Ответ:

Такой способ вызывает внешнюю программу glob (также, как и способ @files=glob("*")). Это неправильно не только потому, что на запуск внешней программы уходит время и ресурсы, но и потому, что где-нибудь этой программы может просто не оказаться. Более правильный способ - это:
   opendir DIR,'/tmp';
   @files=readdir DIR;
   closedir DIR;

или 

   opendir DIR,'/tmp';
   while $file (readdir DIR)
   {
   }
   closedir DIR;
   
Заметьте, что в $file будут подставляться как имена файлов, так и имена подкаталогов. Несколько подсказок. Чтобы прочесть список файлов, в котором не содержалось бы '.' и '..', можно написать следующее:
   opendir DIR,'/tmp';
   @files=grep !/^\.+$/,readdir DIR;
   closedir DIR;
Таким же способом,- с помощью regexp,- можно задавать любые другие маски файлов. Если вы хотите прочесть список каталогов, не трогая файлы:
   opendir DIR,/tmp';
   @dirs=grep {!/^\.+$/ and -d "/tmp/$_"} readdir DIR;
   closedir DIR;
 

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

Ответ:

В этом есть две причины, во-первых необходимо выдавать правильные заголовки, во-вторых на некоторых веб-серверах необходимо переводить потоки ввода-вывода в бинарный режим, лучше это делать всегда. Если Вы берете файл из картинки, можете воспользоваться следующим примером: Чтобы сервер запускал скрипт и выдавал результаты его работы, необходимо объяснить серверу, что этот файл - исполняемый. Существующее в unix-системах понятие "атрибуты файла" отличается от атрибутов в DOS/Windows, и в unix исполняемый файл определяется не расширением, а атрибутом. Если сервер работает на unix-системе, необходимо проставить на файл атрибуты исполняемого файла. Это делает команда "chmod 0755 file", если вы работаете через telnet или ssh, или же продвинутый FTP-клиент типа CuteFTP или FAR ftp plugin. Атрибуты файла, который могут исполнять все желающие (в том числе и сервер), выглядят в буквенном представлении, как
-rwxr-xr-x
 

При попытке запустить скрипт происходит Internal Server Error! Что это за ошибка?

Ответ:

Это, строго говоря, просто сообщение об одной из ошибок, приведших к невозможности нормального выполнения скрипта. Чаще всего возникает в следующих случаях:
в первой строке нет или неправильно указан путь к perl. 
обычно это
#!/usr/local/bin/perl или #!/usr/bin/perl

Файл со скриптом содержит DOS-овые концы строк 0x0D 0x0A. 
В юниксе конец строки - только 0x0A. Чтобы исправить это, 
воспользуйтесь соотв. возможностью редактора FAR, или при 
закачке скрипта на ftp используйте ASCII-режим вместо бинарного.

Скрипт не выводит ничего во время работы. Hеобходимо, 
чтобы он выводил хотя-бы content-type заголовок, например:


   print "Content-type: text/html\n\n";
   print "All done";

Обратите внимание на двойной перевод строки в конце заголовка.
Если у вас нет доступа к логу ошибок сервера, для отладки 
скрипта используйте директиву

use CGI::Carp qw (fatalsToBrowser);
В этом случае при фатальной ошибке, приводящей к завершению скрипта,
 эта ошибка будет видна вам в браузере.
 
 

А можно ли узнать IP юзера, запустившего скрипт через прокси?

Ответ:

: $ENV{'HTTP_X_FORWARDED_FOR'}. Hо не все прокси обеспечивают IP сидящего за ними юзера. "Честные" прокси,- у провайдеров, например,- это делают. А некоторые халявные прокси-сервера, могут и не показывать IP сидящего "за" ними пользователя.
 

Как запускать скрипт на сервере через определенные промежутки времени, или в определенное время суток, день недели, месяц?..

Ответ:

Это возможно, если есть шелл-доступ на сервер. Читайте man crontab
 

Можно ли проверить, жив ли определенный e-mail адрес?

Ответ:

В общем случае - нельзя. Проверка существования и функционирования домена, в котором этот email прописан, в сущности ничего не дает. Остается отталкиваться от конкретных требований. Например, послать e-mail на этот адрес и попросить ответить, зафиксировав ответ.
 

Почему в тексте html, выводимом скриптом, не работают директивы SSI?

Ответ:

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

Что такое mod+perl?

Ответ:

Hа пальцах - модуль к серверу Apache, который предназначен в первую очередь для ускорения запуска скриптов. Вместо того, чтобы каждый раз при запуске скрипта запускался perl, компилировал скрипт и выполнял его, этот perl все время запущен, и висит в памяти. В памяти же находятся и уже откомпилированные до состояния исполняемого кода скрипты.
 

Hаписание скриптов под mod_perl чем нибудь отличается от написания обычных CGI скриптов?

Ответ:

Вообще говоря, да. Во-первых, существует куча более других способов писания под 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 restart)
 

Как сделать так, чтобы скрипт работал в фоновом режиме, как демон?

Варианта два. Первый - воспользоваться модулем Proc::Daemon, второй - сделать все самому, примерно так:

use strict;
require 'sys/syscall.ph';

# Устанавливаем путь по умолчанию
$ENV{PATH} = '/bin:/usr/bin';
  
# Чисто для прикола
$0='mydaemon';  

# Отделяемся от родителя
fork() && exit;  

# Отключаемся от терминала
close STDOUT; close STDERR; close STDIN;

# Делаем корень текужим каталогом
chdir '/';

# Создаем новую сессию и становимся лидером
# группы процессов, чтоб нас случайно не прибили
syscall(&SYS_setsid);

# Перехватываем сигналы, для корректного выхода
$SIG{'INT'} = $SIG{'QUIT'} = $SIG{'TERM'} = 'quit';
$SIG{'HUP'} = 'ignore';

# Делаем наши темные дела
...  

# Выходим  
quit();
  
sub quit {
  # Помещаем сюда код для корректного  
  # прекращения работы
  ...  
  exit(0);
}  

Если Вы хотите написать демона, реализующего работу через сеть, рекомендуем ознакомиться с модулем Net::Daemon.


 

Как сдеалать так, чтобы программа гарантированно работала только в одном экземпляре?

Способ первый, принятый в мире Unix:

$pidfile = '/var/run/mydaemon.pid';

if (-e $pidfile) {
  # aha, pid file is here, but process could be dead by now  
  my $myfile=file_name($0);
  unless (open(PIDFILE,$pidfile)) {  
    # too dangerous to start because I can't read old PID  
    exit 1;
  }  
  my $oldpid=;  
  close PIDFILE;
  # see if there is a process with such pid  
  if ($oldpid > 1 && kill(0,$oldpid)) {  
    # another proccess is running already
    exit 1;  
  } else {  
    # that process is long dead
  }  
}  

# write pid file  
open (PID, ">$pidfile") or die;  
print PID $$;
close(PID);  
  
# do some work
...  
  
# remove pid file
unlink $pidfile;  
exit(0);  

Способ второй, основанный на блокировании файлов: 
# make a lock  
$lockfilename="/tmp/mydaemon.lock";
unless (open (LOCKFILE,">$lockfilename")) {  
  die "cannot open lock file\n";  
}
unless (flock (LOCKFILE,LOCK_EX|LOCK_NB)){  
  print "my copy is already running\n";  
  exit(0);
}  
  
# do some work
...  

# unlock lock file  
close(LOCKFILE);
unlink($lockfilename);  
 

Где взять версию Perl для Windows?

Perl для Windows можно взять на web-сайте Active State Tool Corp. - http://www.activestate.com. Дополнительные пакеты (DBI, GB, MD5, LWP) для Perl под Windows - http://www.activestate.com/PPMpackages/. Полезные советы по работе с Perl под Windows (настройка работы под MS IIS, работа с ADO и ODBC) можно посмотреть на Robin's Perl for Win32 pages.


 

Как инсталлировать дополнительные модули Perl для Windows?

Вариант I - инсталляция из сети:

В состав поставки ActivePerl входит инструмент для инсталляции пакетов Perl Package Manager (PPM). Для инсталляции необходимого Вам пакета нужно запустить PPM, например, в ДОС сессии, набрав команду

C:\>ppm

после этого можно инсталлировать нужный пакет (модуль):

install <имя_модуля>

(пример: install DBD-CSV)

PPM установит его и пропишет в прилагаемый файл документации.

Вариант II - инсталляция скаченного пакета (модуля):

Вам нужно разархивировать скаченный модуль. После этого найти файл, соответствующий названию пакета и имеющий расширение '.ppd', и набрать команду:

ppm install <файл с расширением .ppd

(пример: ppm install libwin32.ppd)

PPM также позволяет Вам паковать свои собственные модули в PPM-пакеты. Дополнительная информация о том, как это сделать, и о том, где взять необходимые для этого программы nmake, tar и gzip содержится в руководстве по ActivePerl в разделе 'ActivePerl Components' -> 'PPM' -> 'How do I make a PPM package?'


 

Как сконфигурировать Микрософт IIS 4.0 для работы с ActivePerl?

Частичный перевод раздела ActivePerl FAQ - Web Server Config из руководства, поставляемого вместе с ActivePerl.

Чтобы настроить IIS или PWS 4.0, для запусков сценариев Perl сделайте следующее:

  1. Запустите IIS 4.0 Internet Service Manager.
  2. Выберите нужную Вам папку (уровень) в дереве директорий из которой будут запускаться Ваши приложения. Вы можете выбрать сервер целиком, веб-сервер, или создать виртуальную директорию.
  3. Выберите пункт из меню.
  4. ...
  5. Нажмите кнопку . Запуститься диалоговое окно конфигурации.
  6. Выбор закладку и нажмите . Запуститься диалог настройки приложений.
  7. Для того, чтобы запускать Perl как приложение CGI, наберите полный путь к Perl.EXE и добавьте в конце %s %s. При запуске Perl сценария в первый %s будет подставляться полный путь на сценарий, а во второй %s -параметры сценария.
  8. Для запуска Perl для ISAPI, наберите полный путь на PerlIS.DLL. Указывать %s %s в этом случае не требуется.
  9. В качестве расширения для приложений (в поле ), укажите .pl или .plx (или то, которое Вы хотите использовать для ваших Perl сценариев).
  10. Настройка теперь завершена. Нажмите <ОК> и нажмите еще раз <ОК> для сохранения изменений.
  11. Закройте IIS 4.0 Internet Service Manager. Так как IIS работает как сервис, Вы должны убедиться в том, что файлы и переменные окружения доступны для него (возможно, Вам придется перезапустить сервис).

Комментарии:

  1. Пункты 4, 5, 6 описывают какое из окон появиться при выборе сервера целиком, веб - сервера и виртуальной директории.
  2. Рекомендую также посмотреть http://www.geocities.com/SiliconValley/Park/8312/perlis.htm - ответы на проблемы с Microsoft Webserver. Там приводятся указания по самостоятельной настройке реестра, описываются различия в работе CGI и ISAPI и т.п.

 

Как получить значение переменной по имени?

Как получить значение переменной, имя которой записано в другой переменной?

Пример 1:

 $var1 = 'lalala';  
 $var2 = 'var1';
 $res = ${$var2};  
 

Значение $res будет - lalala

Пример 2 (посложнее):

 $complex_var = 'qqqq';
 $simplex_var = 'zzzz';  
 $modifier = 'complex';
 $result = ${"${modifier}_var"};  

            

Значение $result будет - qqqq


 

Можно ли скомпилировать из Perl исполняемый файл?

Вы можете воспользоваться программой Perl2Exe. Это утилита для преобразования Perl сценариев в выполняемые файлы, не требующие присутствия интерпретатора языка Perl.

Perl2Exe может сгенерировать модули для Win32 и многих клонов Unix.

Perl2Exe также позволяет Вам создавать не консольные программы, с использованием Tk.

Разработчик - IndigoSTAR Software. "Домашняя страница"

Еще один продукт IndigoSTAR Software - SendMail for Windows(TM) - Windows версия популярной программы Unix Sendmail. Она позволяет отправлять сообщений из командной строки, CGI сценария или BAT-файла.


 

А как мне проверить соответствие введенного пароля зашифрованному?

Первых два символа пароля соджержат шифровальный ключ. Если взяв их зашифровать проверяемый пароль, то зашифрованные строки должны совпасть. Пример:

if (crypt($entered_passwd,subst($crypted_passwd,0,2))   
  eq $crypted_passwd) {
# Пароль верен  
} else {
# Пароль не верен  
}

 

Как получить статистику по файлу (время создания, изменения и т.п.)?

Как минимим двумя способами!

Вариант 1:

if (-e $filename) { print "Файл существует.\n"; }  
if (-z $filename) { print "Файл существует с нулевым размером.\n"; }
if ($size = -s $filename) { print "Файл существует, размер $size.\n"; }  

if (-r $filename) { print "Файл может мной читаться.\n"; }  
if (-w $filename) { print "Файл может мной исправляться.\n"; }
if (-x $filename) { print "Файл может исполняться.\n"; }  
if (-o $filename) { print "Файл мой!\n"; }
  
if (-f $filename) { print "Файл - это файл.\n"; }
if (-d $filename) { print "Файл - это каталог.\n"; }  
if (-l $filename) { print "Файл - это символическая ссылка.\n"; }
if (-p $filename) { print "Файл - это FIFO.\n"; }  
if (-S $filename) { print "Файл - это сокет.\n"; }
if (-b $filename) { print "Файл - это блок-ориентированный файл.\n"; }  
if (-c $filename) { print "Файл - символьное спец. устройство.\n"; }
if (-t $filename) { print "Файловый манипулятор открыт для терминала.\n"; }  

if (-u $filename) { print "У файла установлен бит setuid\n"; }  
if (-g $filename) { print "У файла установлен бит setgid\n"; }
if (-k $filename) { print "У файла установлен бит запрета (бит-липучка)\n"; }  

if (-T $filename) { print "Файл - текстовый.\n"; }  
if (-B $filename) { print "Файл - двоичный.\n"; }
  
$modific_time = int(-M $filename);
print "возраст файла (с момента изменения) в днях $modific_time.\n";  
$access_time = int(-A $filename);
print "дней с последнего чтения файла $access_time.\n";  
$ctime = int(-C $filename);
print "возраст изменения файлового дескриптора в днях $ctime";  

Вариант 2:

Воспользоваться функцией stat

stat FILEHANDLE
stat EXPR

stat возвращает список из 13-ти элементов. Параметры FILEHANDLE - дескриптор, или EXPR - название. Если EXPR опускается, это равносильно вызову stats `$_.

В случае неудачи возвращает пустой список.

($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);

где:

    0 dev      device number of filesystem  
    1 ino      inode number
    2 mode     file mode  (type and permissions)
    3 nlink    number of (hard) links to the file
    4 uid      numeric user ID of file's owner  
    5 gid      numeric group ID of file's owner
    6 rdev     the device identifier (special files only)  
    7 size     total size of file, in bytes
    8 atime    last access time in seconds since the epoch  
    9 mtime    last modify time in seconds since the epoch
    10 ctime    inode change time (NOT creation time!) in seconds since the epoch  
    11 blksize  preferred block size for file system I/O
    12 blocks   actual number of blocks allocated  

Модуль File::stat обеспечивает удобный, механизма доступа к файлам по именам:

Примеры:

    ($READ_TIME, $MOD_TIME) = (stat($filename))[8,9];  
    $READ_TIME = localtime($READ_TIME);
    $MOD_TIME = localtime($MOD_TIME);  
    print "\n последнее обращение к $filename- $READ_TIME";  
    print "\n последнее изменение $filename- $MOD_TIME";

    $mode = (stat($filename))[2];
    printf "Права доступа к файлу %04o\n", $mode & 07777;

 

Как можно стандартизировать (оформить в виде процедуры) получение выборки из БД, чтобы получать набор записей с именованными полями?

Это можно сделать так:

sub QueryArrayOfHashes  

  my ($DB, $query) = @_;  
  my ($result,$data_hash,@items,$key,$val,%hash);
  
  $result = $DB->prepare($query);
  $result->execute or return;  
  while ($data_hash=$result->fetchrow_hashref)
  
    %hash=%$data_hash;
    push @items,{%hash};  
  }
  $result->finish;  
  @items;
}  

Комментарии:

$data_hash - ссылка на хэш

%$data_hash == %{$data_hash} - получение самого хэша из ссылки

{%hash} = разименованный хэш - чтоб получился массив хэшей, а не просто один массив

@items в данном случае == return @items

Пример использования:

use DBI;
...  
$dbh=DBI->connect('DBI:mysql:mysql:localhost', $user, $password,
                    {RaiseError => 1})  
            or die "connecting : $DBI::errstr\n";
  
@res = QueryArrayOfHashes($dbh, "select user, password from user");
for ($i=0; $i<=$#res; $i++) {  
    print "\n[Record #$i]::\n";
    foreach $key (sort keys %{$res[$i]}) {
        # запись вида $a[1]{b} эквивалентна $a[1]->{b}
        print  $key, "\t", $res[$i]{$key}, "\n";
    }
}

$dbh->disconnect;

 

Как мне сделать аутентификацию на Перле, а не средствами веб-сервера?

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

print "WWW-Authenticate: Basic realm=\"что то там\"\n";  
print "Status: 401 Unauthorized\n\n";
print "Ошибка авторизации!\n";  

При этом "что то там" - это имя области авторизации, по правилам для области с одним именем должен всегда срабарывать один и тот же пароль. Проблема заключается в том, что ответ пользователя сидит в заголовке HTTP-запроса, в поле Authorization, которое скрипту через переменные окружения не передаётся. Для сервера Апаче эта проблема решается прописыванием в файле конфигурации следующих строк:

RewriteEngine on  
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_CGI_AUTHORIZATION:%1]  

Всё что он делает - это добавляет в переменную окружения HTTP_CGI_AUTHORIZATION, в которую пишется содержимое HTTP заголовка Authorization, таким образом означенное поле становится доступным для анализа внутри скрипта. Формат этого поля следующий: "login:password", причём эта строка закодирована в Base64, получить эти составляющие можно так:

use MIME::Base64;
$ENV{HTTP_CGI_AUTHORIZATION} =~ s/basic\s+//i;  
($REMOTE_USER,$REMOTE_PASSWD) =
  split(/:/,decode_base64($ENV{HTTP_CGI_AUTHORIZATION}));
 

Как сделать upload картинки через форму?

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

use CGI qw/:standard/;
  
# Код для формы
print "Content-Type: text/html\n\n";  
print <<EOF;
<html><head><title>file upload</title></head>
<body>
<form method="post" enctype="multipart/form-data" action="upload.pl">
<input type="file" name="picture">
<input type="submit" name="Submit" value="Submit">
</form>
</body>
</html>
EOF  

insert_image() if (param());  

sub insert_image {
  # путь к директории для закачки директория
  # должна иметь право на запись для
  # пользователя, под которым работает веб-сервер
  my $downpath = "download/";

  my $in=param('picture');

  # выделяем имя файла из параметра
  my ($name) = $in =~ m#([^\\/:]+)$#;

  open(OUT,">$downpath$name");
  binmode(OUT);
  # читаем входной поток и пишем в файл
  while (<$in>) {
    print OUT $_;
  }
  close(OUT);

  # выводим надпись о закачке файла <$name>
  print "<h2>Upload file: $name</h2>";
}
     


Партнёры и спонсоры проекта:

Все материалы сайта распространяются по лицензии GNU/GPL
© ProUNIX 2003-2009, UnixLib 2005-2009, SoftLib 2006-2009.