Как сделать так, чтобы скрипт работал в фоновом режиме, как демон?
Варианта два. Первый - воспользоваться модулем 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 сделайте следующее:
- Запустите IIS 4.0 Internet Service Manager.
- Выберите нужную Вам папку (уровень) в дереве директорий из которой будут запускаться Ваши приложения. Вы можете выбрать сервер целиком, веб-сервер, или создать виртуальную директорию.
- Выберите пункт из меню.
- ...
- Нажмите кнопку . Запуститься диалоговое окно конфигурации.
- Выбор закладку и нажмите . Запуститься диалог настройки приложений.
- Для того, чтобы запускать Perl как приложение CGI, наберите полный путь к Perl.EXE и добавьте в конце %s %s. При запуске Perl сценария в первый %s будет подставляться полный путь на сценарий, а во второй %s -параметры сценария.
- Для запуска Perl для ISAPI, наберите полный путь на PerlIS.DLL. Указывать %s %s в этом случае не требуется.
- В качестве расширения для приложений (в поле ), укажите .pl или .plx (или то, которое Вы хотите использовать для ваших Perl сценариев).
- Настройка теперь завершена. Нажмите <ОК> и нажмите еще раз <ОК> для сохранения изменений.
- Закройте IIS 4.0 Internet Service Manager. Так как IIS работает как сервис, Вы должны убедиться в том, что файлы и переменные окружения доступны для него (возможно, Вам придется перезапустить сервис).
Комментарии:
- Пункты 4, 5, 6 описывают какое из окон появиться при выборе сервера целиком, веб - сервера и виртуальной директории.
- Рекомендую также посмотреть 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 EXPRstat возвращает список из 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>"; }