Показаны сообщения с ярлыком Perl. Показать все сообщения
Показаны сообщения с ярлыком Perl. Показать все сообщения

понедельник, 23 января 2012 г.

Can't locate MySQL.pm in @INC

Причины ошибки:
From http://search.cpan.org/~capttofu/DBD-mysql-3.0008/lib/Mysql.pm#DESCRIPTION

"As of March 1998, the Msql and Mysql modules are obsoleted by the DBI drivers
DBD::mSQL and DBD::mysql, respectively. You are strongly encouraged to implement
new code with the DBI drivers. In fact, Msql and Mysql are currently implemented
as emulations on top of the DBI drivers."

Фикс:
cpan
force install Bundle::Mysql

вторник, 13 сентября 2011 г.

Работа с geoip из Perl в Debian

Устанавливаем ПО:
apt-get install -y libgeo-ip-perl

Вызываем из кода:
perl -e 'use Geo::IP; my $gi = Geo::IP->open("/usr/share/GeoIP/GeoIP.dat", GEOIP_STANDARD); print $gi->country_code_by_addr("81.21.yy.xx");'

В ответ скриптом будет выдан

воскресенье, 5 декабря 2010 г.

Очень простое написание демонов на Perl с использованием Proc::Daemon (Debian)

Для сабжа есть прекрасный модуль:
http://search.cpan.org/~deti/Proc-Daemon-0.05/lib/Proc/Daemon.pod

Также для защиты от запуска нескольких экземпляров нам понадобится модуль Proc::PID::File.

Устанавливаем его и модуль Proc::PID::File:
apt-get install -y libproc-daemon-perl libproc-pid-file-perl

Начинаем использовать:
#!/usr/bin/perl

use strict;
use warnings;

use Proc::Daemon;
use Proc::PID::File;

# Daemonize
Proc::Daemon::Init();

# Если демон уже запущен, то просто выходим.
if (Proc::PID::File->running()) {
print "Already running\n";
exit 0;
}

# инициализируем демона

# Enter loop to do work
for (;;) {
# выполняем циклическую задачу
}

Вот и все :)

Предвкушая вопрос, почему проверяем демона на существование после демонизации:
Returns true when the process is already running. Please note that this call must be made *after* daemonisation i.e. subsequent to the call to fork(). If the verify flag was set during the instance creation, the process id is verified, alternatively the flag may be passed directly to this method.

По поводу защиты от запуска нескольких экземпляров - она работает прекрасно, pid файл создается в папке /var/run:
ls -la /var/run/ | grep pl
-rw-rw-rw- 1 root root 6 2010-12-05 21:21 mydaemon.pl.pid

Источник: http://www.perlmonks.org/index.pl?node_id=478839

понедельник, 4 октября 2010 г.

Почему так называется Perl функция y///?

В оф документации об этом ни слова. В исходниках нашел следующее:
x2p/s2p.PL:# makey - construct Perl y/// from sed y///

То есть, в Perl (1987 год создания) эта функция была перенята из sed (1973-1974 годы создания). Но вот почему там она так называлась в sed man умалчивает :)

y/source/dest/
Transliterate the characters in the pattern space which appear in source to the corresponding character in dest.

Кто отгадает загадку первым?

четверг, 17 июня 2010 г.

Защита от запуска нескольких инстансов (экземпляров) Perl / Python скриптов

Решение для Perl

Стоит задача - есть некий скрипт, который производит определенные действия с определенной периодичностью. Вызов скрипта в определенном случае может заблокироваться (допустим, ожиданием ввода-вывода). При этом следом может запуститься вторая копия скрипта (интервал не велик), третья и далее. Что в итоге приведет к тому, что система после разблокировки рухнет. Допустим, наш скрипт зовут: /usr/bin/ispmanager_fix_fastcgi и написан он на Перле.

Для начала алгоритм - узнаем имя текущего скрипта (ну не захардкоживать же его в самом деле), грепаем выдачу ps aux (текущие запущенные в системе процессы) на предмет наличия указанного. Если находим, то просто завершаемся - значит предыдущий запуск скрипта еще продолжает работать.

Во-первых, тут нам понадобится спец-переменная $0, которая содержит имя исполняемой программы. В моем случае это будет "/usr/bin/ispmanager_fix_fastcgi". То есть, код будет такой:
ps aux | grep "/usr/bin/ispmanager_fix_fastcgi"
Далее нам надо будет исключить из выдачи ps aux скрипт, из которго сделан запрос проверки. Тут нам поможет встроенная переменная $$, содержащая pid текущего процесса, который в пределах системы, разумеется, уникален. То есть, у нас получается нечто вида:

ps aux | grep "/usr/bin/ispmanager_fix_fastcgi" | grep -v "pid"


Также в выдачу ps aux обязательно попадет сам grep, поэтому его также нужно исключить:

ps aux | grep "/usr/bin/ispmanager_fix_fastcgi" | grep -v "pid" | grep -v grep


Итого получается следующий Perl код:

#!/usr/bin/perl

use strict;
use warnings;

unless ( system("ps aux | grep $0 | grep -v grep | grep -v $$ | grep -v '/bin/sh -c' > /dev/null") ) {
print "Duplicate!\n";
exit 0; # another copy already running
}

# тут код параллельного запуска которого мы и собираемся избегать

Исключение /bin/sh -c добавлено для Debian cron, где каждая cron задача запускается как два процесса.


Конечно, решение не подойдет для форкащихся процессов, которые имеют одинаковые имена, не подойдет оно и для скриптов запускающихся друг за другом, но если интервал между запусками велик и от него не зависят жизни людей (тут уже ключевые слова звучат, например, как "flock"), то юзать вполне можно :)

Как вариант "красивого решения", могу предложить модуль: Proc::ProcessTable, который на Debian ставится вот так:
apt-get install -y libproc-processtable-perl

Решение для Python

Логику рассуждений повторять не буду, приведу лишь код.

import os

pid = os.getpid()
Nil, scriptname = os.path.split(sys.argv[0])

result = os.system("ps aux | grep '" + scriptname + "' | grep -v grep | grep -v '" + str(pid) + "' > /dev/null" )

if result == 0:
    print "Another copy of script already running"
    sys.exit(0)

четверг, 22 апреля 2010 г.

суббота, 30 января 2010 г.

Catalyst: конфигурация модели

Сабж довольно частый -- очень удобно иметь единый конфиг, а не размазаный по десятку модулей. Сходя найти решение "как передать конфигу в модель" не нашёл, но спас Гугл: http://blog.jrock.us/articles/Catalyst%20Tips:%20Part%201.pod

Пишем простейший фильтр исходных кодов

Вот сегодня на очередном совещании по работе мне напомнили про такую суперскую вещь как "фильтры исходных кодов"; я давно хотел их попробовать, но постоянно забывал, что же! Пора =)

Исходный код вот:

package MyFilter;

use Filter::Util::Call;

sub import {
my ($type) = @_;

my ($ref) = [];
filter_add(bless $ref);
}

sub filter {
my ($self) = @_;
my ($status);


s/"([a-zA-Z]+)"/"uc $1"/eg
if ($status = filter_read()) > 0;

$status;
}

1;


Запускаем:
perl -MMyFilter -e 'print "AaAaaaA"'
AAAAAAA


Уж и стоит ли мне говорить, что посредством такого супердвижка можно легко написать на Перле свой ДЯП ?)

пысы: кого воткнуло, идём читать: http://perldoc.perl.org/perlfilter.html

О $c->model

В документации по Каталисту на Цпане сказано:
If the name is omitted, it will look for - a model object in $c->stash->{current_model_instance}, then - a model name in $c->stash->{current_model}, then - a config setting 'default_model', or - check if there is only one model, and return it if that's the case.


Обращаем внимание на последний пункт по причине, что он нифига не работает, т.е. чтобы обращаться по $c->model() (вместо $c->model('MyModelName')) надо ОБЯЗАТЕЛЬНО вписать в конфиг параметр default_model: VashModel и только после этого оно заработает. Так понимаю, это бага.

Интересное решение для автозаполнения форм

Вот, прошу: http://search.cpan.org/~icd/Catalyst-Plugin-AutoSession-0.02/AutoSession.pm

Список почти всех расширений для Каталиста

http://search.cpan.org/~hkclark/Catalyst-Manual-5.7020/lib/Catalyst/Manual/Plugins.pod

Как создать объект, конструируемый на этапе старта Каталиста

Как создать объект конструируемый на этапе старта Каталиста, который потом использовался всеми контроллерами до окончания работы Каталиста ? А вот так: http://community.livejournal.com/ru_catalyst/9867.html

И вопрос и ссылка заимствованы с вышеуказанного урла.

Перенос PAR пэкаджа с 32 битной на 64 битную платформу

Я уже говорил, что PAR кроме pm модулей на чистом Перле складывает в свой архив .so расширения, и обещался провести эксперимент переноса рабочего приложения с 32 битной на 64 битную платформу.

Внимание, рабочая машинка имеет конфу (сервер, никаких спец модулей для Perl нету):
2.6.18-ovz-smp-alt14 #1 SMP Wed May 2 15:41:34 MSD 2007 x86_64 x86_64 x86_64 GNU/Linux
девелоперская:
Linux nrg-desktop 2.6.24-22-generic #1 SMP Mon Nov 24 18:32:42 UTC 2008 i686 GNU/Linux

Как собрать PAR пэкадж я уже говорил в http://perlaround.blogspot.com/2009/03/par-catalyst.html, сейчас обсудим комплекс мер по подготовке второй системы к приёму пэкадажа :)

Ставим PAR: sudo cpan PAR PAR::Packer (возможно, PAR::Packer придётся ставить через cpan force).
Переливаем пэкадж на новую машину каким-то образом (я предпочитаю sftp, т.к. он сходу работает в Гноме).

Запускаем и обламываемся:

Can't load '/tmp/par-nrg/cache-e463425e9fd4743fd99b42ffc3b1f2aee266f2aa/2b152795.so' for module HTML::Parser: /tmp/par-nrg/cache-e463425e9fd4743fd99b42ffc3b1f2aee266f2aa/2b152795.so: неправильный класс ELF: ELFCLASS32 at /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/DynaLoader.pm line 230.
at /usr/lib/perl5/site_perl/5.8.8/PAR/Heavy.pm line 109
Compilation failed in require at HTML/Entities.pm line 147.
Compilation failed in require at Catalyst/Engine.pm line 8.
BEGIN failed--compilation aborted at Catalyst/Engine.pm line 8.
Compilation failed in require at (eval 19) line 3.
...propagated at /usr/lib/perl5/5.8.8/base.pm line 85.
BEGIN failed--compilation aborted at Catalyst/Engine/CGI.pm line 4.
Compilation failed in require at (eval 18) line 3.
...propagated at /usr/lib/perl5/5.8.8/base.pm line 85.
BEGIN failed--compilation aborted at Catalyst/Engine/HTTP.pm line 4.
Compilation failed in require at ./script/catapp_server.pl line 9.
BEGIN failed--compilation aborted at ./script/catapp_server.pl line 10.


Как вариант, можно попробовать собрать в Пэкадж ещё и сам Перл интерпретатор (дада, вы не ослышались!), делается это так pp -o имя_нового_пэкаджа_с_перлом catapp_server.par, но в моём случае это тоже не помогло.

Что же, пока принимаю поражение, но не сдаюсь.

Добавление: вообще, вариант проблему решить посредством виртулизации, например, на qemu -- т.е. собрать дистрибутив, в котором будет 1) ядро ОС 2) Перл 3) Всё необходимое для пуска Перла и в таком виде его раздавать :) Но тут возникает ещё большая куча проблем -- как быть с диском для виртулки, как работать с сетью и проч. Так что тоже для мелочи не вариант.

Часть инфы взята из: http://catalyst.infogami.com/cookbook/par

Сборка PAR пэкаджа для Catalyst приложения

Как известно, Каталист имеет туеву кучу зависимостей и развернуть его на системе, где разработка на перле производится впервые довольно проблематично и может вылиться часа в 3 времени, решение задачи довольно очевидно -- собрать все нужные модули и засунуть в архив вместе с аппликацией. Впрочем, так и поступает PAR (Perl Archive Toolkit), их офсайт тут: http://par.perl.org

Но, как многие могли догадаться, проблем мы огребём по полной в случае завязывания приложения на XS модули, которые, во-первых, не так легко перетащить, а во-вторых, не так легко заставить работать под разными платформами (у меня, например, рабочая машинка 32 битная, а почти все на работе -- 64 битные). Но на наше счастье, Каталист не требует XS расширений (разве что опциональное XS Stash для Template Toolkit). Ладно, давайте проверим PAR в деле, а там разберемся, какие проблемы вылезут.

Ставим сам PAR: sudo cpan PAR PAR::Packer
Собираем пэкадж: переходим в папку с нашим Каталист проектом и вызываем: perl Makefile.PL после этого запускаем make catalyst_par и ждём, пока Пэкадж соберётся.

Следовало бы заметить, что PAR пэкадж запустится далеко не на любой системе, по крайней мере нам будет нужен Perl и сам PAR (в идеале, конечно же, было бы заиметь его в менеджере пакетов, тогда развертывание Перл приложений вообще превратилось в нечто сверх банальное).

Не знаю как у вас, но у меня PAR пэкадж собрался и весит 1,7 мегабайта, что же, попробуем его запустить! Для запуска используется программа "parl" (отличие от "perl" во второй букве), ну что пускаем!

После запуска видим нечто вот такое:

parl catalystapp.par
Usage:
[parl] catalystapp[.par] [script] [arguments]

Examples:
parl catalystapp.par catalystapp_server.pl -r
myapp catalystapp_cgi.pl

Available scripts:
catalystapp_cgi.pl
catalystapp_create.pl
catalystapp_fastcgi.pl
catalystapp_server.pl
catalystapp_test.pl


Как подсказывает хелп, пускать надо вот так: parl catalystapp.par catalystapp_server.pl -p 80, делаем это и вуаля! Каталист аппликация пустилась и отлично работает! =)

Ну что же, попробую сейчас сделать наконец-то таки панель для нашего хостинга и проверить её развертывание таким образом.

Да, кстати, по поводу огребания от XS -- PAR складывает .so модули в папочку по имени /lib/auto/ (папочку?! да, вы угадали, PAR -- это обычный архив). Вот интересный вопрос будет, что произойдёт при запуске на платформе другой архитектуры, что же, это мы попробуем прямо сейчас, но опишу в другом посте.

Создание собственных модулей для CPAN

Я создаю новые каркасы модулей следующей командой: h2xs --omit-XS --omit-autoload --force --version=0.01 --compat-version=5.8.8 --name Google::Charts1

В результате будет создана следующая структура:

Writing Google-Charts1/lib/Google/Charts1.pm
Writing Google-Charts1/Makefile.PL
Writing Google-Charts1/README
Writing Google-Charts1/t/Google-Charts1.t
Writing Google-Charts1/Changes
Writing Google-Charts1/MANIFEST


Сходу два недостатка: всё завязывается на Exporter + не генерируется привычный многим Build.PL.

А есть ли аналоги? Конечно! http://search.cpan.org/~jkeenan/ExtUtils-ModuleMaker-0.51/lib/ExtUtils/ModuleMaker.pm

To create a distribution containing only Perl code. ExtUtils::ModuleMaker is intended to be an easy-to-use replacement for this use of h2xs.


Но модуль нестандартный, поэтому его надо поставить: sudo cpan ExtUtils::ModuleMaker и изучить самостоятельно :)

Создание и запуск простейшего Catalyst приложения

Ну тут всё банально донельзя:

catalyst.pl my_test_catalyst_app
cd my_test_catalyst_app/
script/my_test_catalyst_app_server.pl -reload -p 80


И после этого встроенный сервер Каталиста будет запущен, в чём можно убедиться, открыв в браузере страницу: http://127.0.0.1