Пятница, 26 сентября

Блог программиста — Perl, Ruby, C#: Как реализовать простой ajax-запрос в приложении Catalyst

Как добавить ajax-запрос при разработке Catalyst-приложения. Создание JSON-представления в Catalyst. Возврат данных в формате json. Изменение набора данных во втором элементе select, в засимости от того, какую строку пользователь выбрал в первом элементе select. Примеры perl-кода, html, js-скрипт. Установка jQuery.   К моему сожалению, конец августа и начало сентября — были для меня крайне непродуктивным […]

Среда, 17 сентября

Мини-портал Perl на Opennet: Девятнадцатый выпуск электронного журнала Pragmatic Perl

Представлен девятнадцатый выпуск Pragmatic Perl, русскоязычного журнала о современном программировании на Perl.

Понедельник, 15 сентября

Меркантильный гуру: .

"Padre is now on GitHub"

А поздно.

Понедельник, 8 сентября

Чтобы не искать: RabbitMQ — Отложенные сообщения, часть 2



В первой части не учел один важный момент. Накатал вторую часть.

Хабрахабр: Метки / perl: RabbitMQ — Отложенные сообщения, часть 2


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

В связи с этим хочу привести более универсальное (но чуть более сложное) решение, позволяющее организовать отложенные сообщения с произвольным временем задержки.
Читать дальше →

Пятница, 5 сентября

Хабрахабр: Метки / perl: Perl Golf на YAPC::Russia 2014




Мы в REG.RU страшно любим участвовать в интересных мероприятиях. Настолько любим, что даже сами стали их организовывать. Например, 13-14 июня, при спонсорской помощи компании и активном участии коллег, мы провели очередную конференцию perl-программистов YAPC::Russia 2014. Как всегда, собралась отличная компания, время было проведено приятно и полезно. К тому же, местом проведения конференции в этом году впервые стал Санкт-Петербург, да ещё и в разгар белых ночей! Немного весёлых картинок с мероприятия можно увидеть в соцсетях (ВКонтакте и Фейсбук), а на YouTube мы даже выложили часть докладов (и всё ещё не теряем надежды выложить остальные).

Помимо прочего культурного досуга, я решил повторить опыт прошлогодней конференции YAPC::Europe и снова провести конкурс Perl Golf.
Читать дальше →

Четверг, 4 сентября

Хабрахабр: Метки / perl: RabbitMQ — отложенные сообщения


image

На Хабре имеется серия переводов официального руководства по RabbitMQ (1, 2, 3, 4, 5). К сожалению, в официальном руководстве не рассматривается вопрос организации отложенный сообщений, а я считаю этот вопрос весьма важным. Поэтому я решал сам написать такую статью.

Примеры кода будут на Перле, но никаких специфических для Перла деталей в коде не будет, поэтому примеры могут быть сравнительно легко адаптированы для любого другого языка.
Читать дальше →

Среда, 3 сентября

Меркантильный гуру: RSS

Задачка сгенерить настоящий валидный RSS, оказывается, не такая уж простая.

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

Хотя, казалось бы, почему XML::RSS из коробки не делает правильно? И, собственно, на кой оно вообще, если масштаб допиливания руками превышает написание всёго нужного ручками?

Вторник, 2 сентября

Хабрахабр: Метки / perl: Блокировка запуска второго экземпляра программы на Perl


image

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

Нужно проверить — является ли запускаемый процесс единственным, запущенным в данный момент, экземпляром программы, или уже есть другой, запущенный экземпляр?

Есть несколько методов такой проверки, отличающихся надежностью.
Читать дальше →

Понедельник, 1 сентября

Хабрахабр: Метки / perl: Mojolicious Perl Style


Хочу описать стиль программирования на языке Perl, к которому я стремлюсь и который в основном перенял от современного web-фреймворка Mojolicious, но наверное много где еще применяется подобный. Мне кажется выработать правильный стиль кодинга — очень важно.

Пример 1:
Методы в одну строку.
Если обращение к каждому аргументу функции происходит лишь один раз, и порядок применения их в коде соответствует порядку переданных аргументов, то предлагается извлекать их с помощью стандартной функции shift, которая если вызывается без аргументов, по-умолчанию работает с массивом @_, в котором хранятся все переданные аргументы функции, выталкивает первый аргумент из массива и возвращает его.

sub node { shift->tree->[0] }
#
sub parse { shift->_delegate(parse => shift) }
#
sub _tag { shift->new->tree(shift)->xml(shift) }


Пример 2:
Сначала извлекаем первый параметр, имя класса например, все остальные аргументы передаем другой функции и пусть она их обрабатывает.
sub tree { shift->_delegate(tree => @_) } 
# т.е. может превратиться в это _delegate(tree => [], deep => 5) или это _delegate(tree => [], 5, 0) 
sub log { shift->emit('message', lc shift, @_) }


Пример 3:
Тоже для метода в одну строчку.
Здесь происходит обращение к одному и тому же аргументу целых 3 раза, потому для доступа к аргументу используется прямое обращение к элементу массива аргументов $_[0].
sub _instance { ref $_[0] ? $_[0] : $_[0]->singleton }
#
sub find { $_[0]->_collect(@{$_[0]->_css->select($_[1])}) }


Читать дальше →

Четверг, 28 августа

Хабрахабр: Метки / perl: [Из песочницы] Асинхронный многопоточный пул воркеров на Perl


image

В работе веб-сервиса, да и вообще многих других систем, часто встречается необходимость выполнения различных фоновых задач. Для этого пишут скрипты — воркеры — которые берут список имеющихся задач и начинают их выполнять — с какой-то скоростью и в какой-то последовательности.

Понятное дело, хорошо, когда все задачи выполняются быстро и без проволочек.

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

  • Научить воркер не ждать выполнения каждого отдельного этапа задачи (асинхронность)
  • Научить воркер выполнять одновременно несколько задач (многопоточность) (disclaimer: на самом деле термин «многопоточность» тут используется в значении «многопроцессность»)

В этой статье мы рассмотрим вариант реализации воркера, который будет одновременно асинхронным и многопоточным.
Читать дальше →

Блог программиста — Perl, Ruby, C#: Использование MongoDB в Catalyst. Часть 1. Примеры кода

Разработка панели администратора, для доступа к системе логов. Создание модели для работы с MongoDB в Catalyst. Создание контроллера и tt-шаблонов для панели администратора. Взаимодействие с MongoDB, выборка данных, сортировка, использование лимитов, поиск одной-единственной записи. Получение списка всех доступных баз данных Mongo. Использование Variable::Eject. Простые примеры кода.   Задача MongoDB используется для хранения логов. Требуется создать […]

Вторник, 26 августа

Чтобы не искать: Асинхронный многопоточный пул воркеров на Perl



В работе веб-сервиса, да и вообще многих других систем, часто встречается необходимость выполнения различных фоновых задач. Для этого пишут скрипты - воркеры - которые берут список имеющихся задач и начинают их выполнять - с какой-то скоростью и в какой-то последовательности.

Понятное дело, хорошо, когда все задачи выполняются быстро и без проволочек.

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

  • Научить воркер не ждать выполнения каждого отдельного этапа задачи (асинхронность)

  • Научить воркер выполнять одновременно несколько задач (многопоточность) (disclaimer: на самом деле термин "многопоточность" тут используется в значении "многопроцессность")

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

Модуль AnyEvent

Для программирования в асинхронном режиме в Перле есть отличный модуль
AnyEvent.

На всякий случай следует сказать, что на самом деле AnyEvent является оберткой над другими низкоуровневыми асинхронными модулями. Как DBI является оберткой и универсальным интерфейсом к разным базам данных, так и AnyEvent является оберткой и универсальным интерфейсом к различным реализациям асинхронных движков.

Для AnyEvent имеется огромное количество всевозможных расширений, в том числе есть и расширение для написания многопоточных приложений - модуль AnyEvent::Fork::Pool.

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

Скрипт

Рассмотрим скрипт anyevent_pool.pl:


-------
#!/usr/bin/perl

use strict;
use warnings;

use AnyEvent::Fork::Pool;

# Модуль воркера
my $mod = 'Worker';
# Функция воркера
my $sub = 'work';

# Определить количество ядер в системе
my $cpus = AnyEvent::Fork::Pool::ncpu 1;

# Создать пул воркеров
my $pool = AnyEvent::Fork
  ->new
  ->require ($mod)
  ->AnyEvent::Fork::Pool::run(
      "${mod}::$sub",        # Модуль::Функция - рабочая функция воркера
      init => "${mod}::init", # Модуль::init - функция инициализации воркера
      max  => $cpus,         # Количество воркеров в пуле
      idle => 0,                   # Количество воркеров при простое
      load => 1,                  # Размер очереди воркера
  );

# Поставить пулу задачи
for my $str (qw{q2 rtr4 ui3 asdg5}) {
   $pool->($str, sub {
      print "result: @_\n";
   });
};

AnyEvent->condvar->recv;
-------

Несмотря на небольшой объем, этот скрипт представляет собой полноценное асинхронное многопоточное приложение.

Разберем его по частям.

Переменные


-------
# Модуль воркера
my $mod = 'Worker';
# Функция воркера
my $sub = 'work';
-------

Эти переменные задают связку между пулом и тем кодом, который будет выполять конкретные фоновые задачи. Пул - он один на всех, а задачи могут быть разные. Эти переменные указывают пулу, какой именно код (какую функцию из какого модуля) вы хотите запустить для выполнения конкретной задачи.

Например, у вас может быть модуль Text для обработки текста, а в модуле функции length и trim. И еще у вас может быть модуль Image, в котором могут быть функции resize и crop. Пулу совершенно без разницы, что делают ваши функции и как они устроены. Вам нужно просто сказать пулу, в каком модуле они находятся и как они называются, и пул их выполнит.

Важно! Модуль воркера не нужно подключать в скрипте через "use Worker". Пул сам автоматически подгрузит модуль воркера, вам нужно только правильно указать название модуля в переменной.

Количество ядер

-------
# Определить количество ядер в системе
my $cpus = AnyEvent::Fork::Pool::ncpu 1;
-------

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

Если по каким-то причинам количество ядер не удалось определить, то будет использоваться значение, указанное вручную. В данном случае это 1.

Пул

-------
# Создать пул воркеров
my $pool = AnyEvent::Fork
   ->new
   ->require ($mod)
   ->AnyEvent::Fork::Pool::run(
      "${mod}::$sub",            # Модуль::Функция - рабочая функция воркера
      init => "${mod}::init", # Модуль::init - функция инициализации воркера
      max  => $cpus,         # Количество воркеров в пуле
      idle => 0,                   # Количество воркеров при простое
      load => 1,                  # Размер очереди воркера
  );
-------

Пояснения к параметрам:

  • Рабочая функция воркера всегда должна указываться первым параметром. Это та самая функция того самого модуля, которую мы указали в двух первых "настроечных" переменных $mod и $sub. Это единственный обязательный параметр.

  • init - Если в вашем воркере есть необходимость инициализации, то в этом параметре можно указать название инициализирующей функции. В даном случае название функции указано как "init", поскольку это обычное название для такой функции, но, в принципе, можно указать любое другое название.

  • max - Этот параметр задает количество потоков, которые будет запускать пул. Именно тут следует указать ранее определенное количество ядер в системе (но если хотите - можете указать любое число, если знаете, что делаете).

  • idle - тут указывается количество воркеров, которые будут ждать "на низком старте". Чем больше это число (но не больше параметра max) - тем быстрее пул среагирует на новую поступившую задачу, но тем больше будет бесполезно ждущих (и жрущих ресурсы) процессов.

  • load - Сколько задач будет отдано каждому воркеру не дожидаясь исполнения предыдущих. Значение сильно зависит от ситуации - в каких-то случаях лучше меньше, в каких-то лучше больше. При прочих равных большее значение должно повышать эффективность работы пула (оптом - дешевле).

Также имеются и другие параметры, которые я здесь не рассматриваю. Они сильно специфичны и требуются редко. С полным списком параметров можно ознакомиться в документации модуля.

Постановка задач пулу

-------
# Поставить пулу задачи
for my $str (qw{q2 rtr4 ui3 asdg5}) {
   $pool->($str, sub {
      print "result: @_\n";
   });
};
-------

Пулу можно передать произвольное количество параметров, но последним параметром должен быть коллбэк. Коллбэк - это анонимная функция, которая будет вызвана после того, как воркер выполнит задачу. В эту функцию будут переданы результаты работы воркера.

Другими словами - эта функция является получателем результатов работы функции $sub. Все, что выдаст функция $sub, будет передано в качестве аргументов в функцию-коллбэк. Условно эту связь можно записать примерно так - "callback($sub)".

В нашем случае функция-коллбэк просто печатает все, что она получает.

Переменная же $str - это, собственно, и есть та самая задача, которую должен выполнить воркер. В нашем случае это просто одна строка (точнее - 4 строки, запускаемых в цикле). Строки тут не имеют никакого глубокого смысла, я просто позвал кота походить по клавиатуре.

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

Запуск движка

-------
AnyEvent->condvar->recv;
-------

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

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


Сам воркер

Теперь возникает вопрос - а где же, собственно, сам воркер? Где код, исполняющий непосредственно работу?


Этот код вынесен в отдельный модуль, который мы указали в переменной $mod.

Вот код модуля Worker:

-------
package Worker;

use strict;
use warnings;

my $file;

sub init {
  open $file, '>>', 'file.txt';

  my $q = select($file);
  $|=1;
  select($q);

  return;
}

sub work {
  my ($str) = @_;

  for (1..length($str)) {
      print $file "$$ $str\n";
      sleep 1;
  };

  return $str, length($str);
}

1;
-------

Как видите, в модуле две функции - init и work.

Функция init инициализирует воркер. В нашем случае функция открывает лог-файл, в который далее будут выводиться результаты работы рабочей функции work. Как уже говорилось выше - функция init является необязательной, в нашем случае я сделал ее просто для наглядности.

Функция work - это главная функция. Это та самая рабочая функция, которая была задана в переменной $sub. Именно в этой функции выполняется вся работа, связанная с выполнением конкретной задачи.

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

Обратите внимание - функция возвращает два значения - саму строку и ее длину. Именно эти два значения будут переданы в коллбэк, заданный на этапе постановки задач пулу (а в коллбэке, как говорилось выше, эти значения будут просто напечатаны).

Вот, собственно, и весь код.

Запускаем пул

Теперь запустим наш пул и посмотрим, что получится:




Тут мы видим результаты работы пула. Можно заметить, что порядок вывода результатов отличается от порядка строк, заданного в цикле в скрипте. Причина понятна - у строк разная длина, поэтому воркеры обрабатывают строки с разной скоростью. Чем проще задача - тем она быстрее выполняется.

Теперь посмотрим не просто на результаты, но и на процесс работы воркеров. Для этого во втором окне запустим tail для лог-файла:



Обратите внимание - результаты работы выводятся вперемешку, так-как задачи выполняются одновременно. Слева видны идентификаторы процессов - видим, что задействованы 4 процесса. У меня в системе 4 ядра, поэтому одновременно выполняются все 4 задачи.

И, наконец, посмотрим на таблицу процессов:



Так выглядит дерево процессов нашего пула.

Первым в списке идет скрипт, далее менеджер пулов (да-да, пулов может быть несколько штук), потом менеджер пула, и, наконец, воркеры.

Если не полениться и сравнить идентификаторы процессов, то можно увидеть, что идентификаторы воркеров совпадают с идентификаторами в лог-файле.

Литература

Понедельник, 25 августа

Сообщество ru_perl в LiveJournal: Проблемы с Active Perl под Win7

До этого Active Perl не пользовался. Работал в Линуксе или Cygwine
Взял скриптик, работающий в Cygwin и запустил из виндовского окошка под Active Perl. Все отработало нормально, но в конце выскочило окошко с надписью "perl command line interpreter has stopped working". Ну и "windows is checking for a solution to the problem"
Потом вторая надпись меняется на "A problem caused the program to stop working correctly. Windows will close the program and notify you if a solution is available"
7-е винды, 64 бита. Перл - 32-битный. Так вышло,что есть 32-битные системы, а потому и перл 32-битный

Есть какие-то идеи,как убрать эту ошибку?
Заранее спасибо

Воскресенье, 24 августа

Ещё один блог сисадмина: Настройка nginx, php5-fpm и uwsgi

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

1. Менеджер процессов php5-fpm

В начале года я заинтересовался менеджером процессов php5-fpm для обслуживания приложений на PHP. Он обладает большим количеством приятных преимуществ, основанных на так называемых пулах. Пул - это группа процессов, выделенная для обработки запросов, поступающих на определённый порт или Unix-сокет. Для каждого пула действует своя политика управления процессами:

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

Ну и самое приятное заключается в том, что для каждого из пулов можно задавать разные настройки PHP или вообще строго фиксировать их, запрещая приложению менять эти настройки самостоятельно. Например, какое-то приложение может требовать для работы много памяти (веб-интерфейс Zabbix, например), другое может долго формировать страницу (например, какое-то веб-приложение, формирующее отчёт), третьему нужно ограничить таймауты подключения к базе данных или время ожидания данных из сокета. В таком случае каждому приложению можно выделить отдельный пул и задать отдельные настройки.

Благодаря своим особенностям php5-fpm очень хорошо подходит для виртуального хостинга, когда на одном сервере может обслуживаться множество приложений разных пользователей. Думаю, что это уже понятно.

Однако, php5-fpm можно хорошо использовать и совместно с Lighttpd. Lighttpd даже в чём-то проще. Например, при совместной работе php5-fpm и Lighttpd мне не приходилось настраивать размеры буферов для чтения заголовков ответов, что может понадобиться сделать при использовании nginx и какого-то приложения, устанавливающего большое количество cookie. Если вам требуется запускать только приложения, написанные на PHP, то связка Lighttpd и php5-fpm может оказаться оптимальным выбором, особенно если вы уже знакомы с Lighttpd.

2. Сервер uwsgi

Позже мне потребовалось запускать веб-приложения, написанные на веб-фреймворках на языках Python и Perl. В этих веб-фреймворках приложение в конечном итоге представляет собой объект, поддерживающий интерфейсы WSGI или PSGI соответственно. Я уже пользовался веб-серверами, которые реализуют HTTP-интерфейс для приложений WSGI и PSGI - это были flup и starman. Оба веб-сервера мне не понравились своей требовательностью к ресурсам, поскольку они написаны на соответствующих интерпретируемых языках, а также необходимостью под каждое веб-приложение создавать отдельный скрипт инициализации. Этих проблем был лишён найденный сервер uwsgi, который написан на Си, имеет удобный сценарий инициализации и позволяет запускать веб-приложения с интерфейсом WSGI и PSGI. С его помощью можно даже запускать приложения Rack, написанные на Ruby. Один недостаток - снаружи он предоставляет не HTTP-интерфейс, а всё тот же WSGI.

Совместно с uwsgi умеет работать nginx, так что выбор такой связки был предопределён. Осталось решить последний вопрос - как запускать классические CGI-приложения? Поначалу я думал воспользоваться сервером spawn-fcgi или fcgiwrap, но потом нашёл CGI-плагин для uwsgi, так что для запуска любого веб-приложения оказалось достаточно лишь php5-fpm и uwsgi, которыми ещё и очень удобно управлять. Несмотря на то, что в uwsgi имеется возможность обслуживать запросы к приложениям на PHP, я всё же предпочёл использовать для PHP сервер php5-fpm, обладающий большим количеством настроек, позволяющих получить больший контроль над PHP-приложениями.

Именно таким образом я и пришёл к решению сменить привычный мне веб-сервер Lighttpd на связку nginx + php5-fpm + uwsgi. В 2008 я перешёл от использования Apache на Lighttpd, в 2014 я сменил Lighttpd на nginx. С тех пор понимание того, каким должен быть хороший веб-сервер кардинально изменилось. Если раньше это был комбайн, в котором было довольно тяжело ориентироваться, то теперь это несколько взаимодействующих программ, каждая из которых очень наглядна, быстро осваивается, радует удобством и скоростью работы.

3. Установка пакетов

Если вы планируете использовать nginx только совместно с php5-fpm, то установить потребуется только два пакета - легкий nginx и сам менеджер процессов:
# apt-get install nginx-lite php5-fpm
Если же вы планируете использовать uwsgi, то вам нужна полная версия nginx и uwsgi-сервер:
# apt-get install nginx-full uwsgi
Дополнительно, в зависимости от того, какие приложения вы собираетесь запускать под управлением uwsgi, вам может понадобиться один или несколько дополнительных пакетов. Для поддержки выполнения CGI-скриптов при помощи uwsgi установите пакет с соответствующим модулем:
# apt-get install uwsgi-plugin-cgi
Если вы планируете запускать Perl-приложения с интерфейсом PSGI, то вам понадобится модуль для поддержки соответствующего протокола:
# apt-get install uwsgi-plugin-psgi
Наконец, uwsgi можно использовать и для запуска WSGI-приложений, написанных на Python. Для этого нужен модуль, называющийся... python:
# apt-get install uwsgi-plugin-python
4. Заготовка файла конфигурации nginx

Создадим заготовку файла конфигурации /etc/nginx/sites-enabled/default:
server {
listen 0.0.0.0:80;
# server_name info.domain.tld;

root /var/www;
index index.html index.php index.pl;
}
В последующих разделах приводятся небольшие фрагменты, которые можно добавить внутрь секции server этой заготовки.

Здесь настраивается виртуальный сервер, принимающий подключения на TCP-порту 80 на любой настроенный на компьютере IP-адрес. Если необходимо выделить несколько виртуальных веб-серверов, работающих на разных IP-адресах, можно создать несколько секций, указав в каждой из них соответствующий IP-адрес.

Если необходимо запустить на одном IP-адресе виртуальные серверы, отличающиеся доменным именем, то можно раскомментировать опцию server_name и указать одно или несколько доменных имён через пробел. Один из таких серверов можно отметить как сервер по умолчанию при помощи ключевого слова default в опции listen в самом её конце - на него будут поступать запросы, для которых не удалось найти секцию с подходящим доменным именем, но поступившие на этот IP-адрес.

Опция root задаёт каталог, из которого будут браться запрошенные файлы. Если имя конкретного файла не указано, а указан лишь каталог, то будут перебираться по очереди имена, указанные в опции index. Первый же существующий файл будет отдан клиенту или обработан как приложение (в зависимости от настроек из последующих секций).

5. CGI-приложения на PHP

Для выполнения приложений на PHP воспользуемся уже упомянутым сервером php-fpm. Создадим файл с описанием пула, который будет обрабатывать запросы к PHP-файлам. Для этого создадим файл /etc/php5/fpm/pool.d/default.conf или приведём имеющийся файл к следующему виду:
; Имя пула
[default]

; Рабочие процессы пула будут работать от имени указанного пользователя и группы
user = www-data
group = www-data

; Пул будет ожидать запросы на указанном Unix-сокете
listen = /var/run/php.sock

; Владелец Unix-сокета, его группа и права доступа к сокету
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

; Динамический менеджер рабочих процессов будет поддерживать от 10 до 30 процессов,
; из которых от 5 до 10 могут простаивать в ожидании поступления новых запросов.
; Если простаивающих процессов будет меньше 5 - будут порождены новые процессы,
; если простаивающих процессов окажется больше 10 - лишние будут завершены
pm = dynamic
pm.max_children = 30
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 10

; Тут можно ограничить количество запросов, последовательно обслуживаемых одним процессом
; После этого процесс будет завершён и запущен снова - это может помочь от утечек памяти
;pm.max_requests = 500

; Если обработка одного запроса длится дольше трёх минут - обработка запроса принудительно завершается
request_terminate_timeout = 180s

; В этом файле можно вести журнал обработанных запросов
;access.log = /var/log/php5-fpm.access.log

; Тут можно задать настройки, которые обычно указывают в файле php.ini
; Разница в том, что эти настройки будут действовать не глобально, а только внутри пула
; Настройки php_admin нельзя поменять изнутри самого PHP-приложения
php_value[data.timezone] = Asia/Yekaterinburg
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php5-fpm.errors.log
;php_admin_value[memory_limit] = 128M
php_admin_value[mysql.connect_timeout] = 1
php5-fpm умеет перечитывать файлы конфигурации, соответствующим образом меняя состав пулов и их настройки, не трогая те пулы, настройки которых не поменялись:
# /etc/init.d/php5-fpm reload
Однако, если вам кажется, что настройки не вступили в силу, можно перезапустить php5-fpm целиком, чтобы он гарантированно прочитал и применил новые настройки пулов, полностью перезапустив их процессы:
# /etc/init.d/php5-fpm restart
Теперь нужно добавить в заготовку файл, например, со следующим содержимым:
location ~ ^/php/(base|index|logout|query)\.php$ {
fastcgi_pass unix:/var/run/php.sock;
include fastcgi_params;
}

location /php/static/ {
alias /usr/local/share/php/static/;
}
В первой секции location перечисляются файлы, запросы к которым будут обрабатываться созданным нами пулом процессов php5-fpm. Во второй секции location указан путь к статическим файлам, отдачей которых будет заниматься сам nginx.

Стоит отметить, что секции без регулярных выражений имеют приоритет над секциями с регулярными выражениями. Первые совпадают с каталогом и всеми подкаталогами и файлами внутри него, вторые - с файлами и каталогами, удовлетворяющими регулярным выражениям. Самым высоким приоритетом обладают секции со знаком =, которые указывают точное соответствие с файлом или каталогом, без подкаталогов.

Осталось перезапустить nginx, чтобы его новые настройки вступили в силу:
# /etc/init.d/nginx restart
nginx тоже умеет перезагружать обновлённую конфигурацию, однако рабочие процессы могут некоторое время продолжать работать со старой конфигурацией, пока не будут вытеснены новыми. Если это не критично, то перезагрузить его можно так:
# /etc/init.d/nginx reload
6. PHP-приложения на фреймворке CodeIgniter

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

Прежде чем приступить к настройке nginx, сначала настроим само приложение - в файле application/config/config.php нужно прописать следующие настройки:
$config['base_url'] = '';
$config['index_page'] = '';
$config['uri_protocol'] = 'REQUEST_URI';
Первые две настройки не заданы, т.к. будет использоваться автоматическое их определение самим фреймворком.

Теперь пришла очередь nginx. Для обработки запросов к приложению будем использовать пул php5-fpm, настройка которого была описана в предыдущем разделе. В нашу заготовку файла конфигурации nginx /etc/nginx/sites-enabled/default.conf добавим следующие настройки:
location /ci/ {
fastcgi_pass unix:/var/run/php.sock;
include fastcgi_params;

fastcgi_buffer_size 64k;
fastcgi_buffers 8 64k;

fastcgi_param SCRIPT_FILENAME /usr/local/share/ci/index.php;
fastcgi_param SCRIPT_NAME /ci/index.php;

fastcgi_read_timeout 120s;
}

location /ci/data/ {
alias /usr/local/share/ci/data/;
}
В первой секции переопределяются некоторые настройки, значения по умолчанию которых нас не устраивают. Важно переопределять их после включения файла с настройками по умолчанию - иначе он сам переопределит заданные нами настройки.

Размеры буферов переопределены, поскольку CodeIgniter интенсивно использует cookie - заголовок запроса или ответа может получиться очень большим и не поместиться в буфер. В этом случае приложение может иногда работать, а иногда - не работать, в зависимости от того, какой объём имеют cookie.

Следующие опции указывают, какой файл будет обрабатывать запросы и помогут фреймворку автоматически определить значения опций base_url и index_page.

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

Не забудьте перезагрузить или перезапустить nginx:
# /etc/init.d/nginx restart
7. CGI-приложения на Perl

Запросы к CGI-приложениям может обслуживать uwsgi с модулем uwsgi-plugin-cgi. В uwsgi нет понятия пулов и нет единственного мастер-процесса, который бы шефствовал над остальными процессами. Вместо этого можно определить несколько раздельных файлов конфигурации, у каждого из которых будет собственный мастер-процесс. Централизованное управление мастер-процессами на данный момент осуществляется при помощи единого init-скрипта.

В новых версиях uwsgi появился режим emperor, который работает полностью аналогично php5-fpm - с одним мастер-процессом. Более того - он умеет обнаруживать появление новых файлов приложений или изменения в имеющихся файлах, поддерживая состав и настройки рабочих процессов актуальными. Однако, в Debian Wheezy эта новая версия uwsgi ещё не попала, поэтому я опишу текущее положение дел.

Определим настройки приложения в файле /etc/uwsgi/apps-enabled/cgi.ini:
[uwsgi]

; Имена рабочих процессов приложения и мастер-процесса
procname = uwsgi-cgi
procname-master = uwsgi-cgi-master

; Используемый плагин и его настройки: корень с файлами, обрабатываемые расширения,
; максимальное время обработки запроса скриптом
plugins = cgi
cgi = /var/www
cgi-allowed-ext = .pl
cgi-timeout = 120

; Рабочих процессов будет четыре - можно будет одновременно обслуживать не более 4 запросов,
; а последующие запросы будут вставать в очередь до освобождения одного из рабочих процессов
processes = 4
Теперь можно перезапустить все приложения или индивидуально - только что созданное:
# /etc/init.d/uwsgi restart
# /etc/init.d/uwsgi start cgi
После запуска нового приложения uwsgi создаст Unix-сокет /var/run/uwsgi/app/cgi/socket, где cgi - имя приложения. Кроме того, будет создан журнал работы приложения в файле /var/log/uwsgi/app/cgi.log, где cgi - опять то же имя приложения.

Задаём настройки nginx, вписав в заготовку файла конфигурации ещё один фрагмент:
location = /pl/index.pl {
uwsgi_pass unix:/var/run/uwsgi/app/cgi/socket;
include uwsgi_params;

# Модификатор для протокола CGI
uwsgi_modifier1 9;
# Скрипт, обрабатывающий запросы
uwsgi_param SCRIPT_FILENAME /usr/local/share/pl/index.pl;
}

location /pl/static/ {
alias /usr/local/share/pl/static/;
}
Значение опции uwsgi_modifier1 берётся из таблицы на странице The uwsgi Protocol. В данном случае используется протокол CGI, значение модификатора - 9.

Не забудьте перезагрузить или перезапустить nginx.

8. Perl с фреймворком Dancer

Для запуска PSGI-приложений под управлением uwsgi нужен файл, возвращающий объект PSGI. Для этого создадим файл приложения /usr/local/share/dancer/bin/app.psgi:
#!/usr/bin/perl

use Dancer;

...

setting apphandler => 'PSGI';

my $app = sub {
my $env = shift;
my $request = Dancer::Request->new(env => $env);
Dancer->dance($request);
};
На месте многоточия располагается тело приложения, где определяются обработчики страниц.

Теперь создадим файл конфигурации веб-приложения /etc/uwsgi/apps-enabled/dancer.ini со следующим содержимым:
[uwsgi]

; Имена рабочих процессов приложения и мастер-процесса
procname = uwsgi-dancer
procname-master = uwsgi-dancer-master

; Настраиваем плагин и задаём количество рабочих процессов
chdir = /usr/local/share/dancer
plugin = psgi
psgi = /usr/local/share/dancer/bin/app.psgi
; Приложение используется редко - запустим два рабочих процесса
processes = 2
Запустим новое веб-приложение:
# /etc/init.d/uwsgi start dancer
В заготовку конфигурации nginx добавим следующий фрагмент:
location ~ ^/dancer/ {
uwsgi_pass unix:/var/run/uwsgi/app/dancer/socket;
include uwsgi_params;

# Указываем модификатор для использования протокола PSGI
uwsgi_modifier1 5;
}

location /dancer/static/ {
alias /usr/local/share/dancer/static/;
}
Осталось перезапустить или перезагрузить nginx.

9. Python и приложение на Django в подкаталоге

При создании проекта Django генерируется файл wsgi.py, внутри которого создаётся WSGI-объект application. Для запуска Django-приложения через uwsgi создадим файл /etc/uwsgi/apps-enabled/dj1.ini с конфигурацией приложения:
[uwsgi]

; Имена рабочих процессов приложения и мастер-процесса
procname = uwsgi-dj1
procname-master = uwsgi-dj1-master

; В пакете на самом деле два плагина - python26 и python27, выбираем плагин python27
plugin = python27
; Каталог проекта Django
chdir = /usr/local/share/dj1
; Используем файл wsgi.py, в котором определяется WSGI-приложение application
module = wsgi:application
; Запустим шесть рабочих процессов
processes = 6
Запустим рабочие процессы приложения:
# /etc/init.d/uwsgi start dj1
А в заготовку конфигурации nginx добавим такой фрагмент:
location /dj1/ {
uwsgi_pass unix:/var/run/uwsgi/app/dj1/socket;
include uwsgi_params;

# Этот модификатор используется для протокола WSGI
uwsgi_modifier1 30;
# Имя скрипта будет вырезаться из URL перед маршрутизацией запроса
uwsgi_param SCRIPT_NAME /dj1;
}

location /dj1/static/ {
alias /usr/local/share/dj1/static/;
}
Осталось перезагрузить или перезапустить nginx.

10. Python и приложение на Django в корне

Создадим файл /etc/uwsgi/apps-enabled/dj2.ini с конфигурацией приложения (здесь всё аналогично предыдущему случаю):
[uwsgi]

; Имена рабочих процессов приложения и мастер-процесса
procname = uwsgi-dj2
procname-master = uwsgi-dj2-master

; В пакете на самом деле два плагина - python26 и python27, выбираем плагин python27
plugin = python27
; Каталог проекта Django
chdir = /usr/local/share/dj2
; Используем файл wsgi.py, в котором определяется WSGI-приложение application
module = wsgi:application
; Запустим шесть рабочих процессов
processes = 6
Запустим рабочие процессы приложения:
# /etc/init.d/uwsgi start dj2
В заготовку конфигурации nginx добавляем фрагмент:
# Здесь нужно перечислить все корневые страницы или подкаталоги со страницами приложения
location ~ ^/(admin|login|logout|app)(/|$) {
uwsgi_pass unix:/var/run/uwsgi/app/dj2/socket;
include uwsgi_params;
}

# Каталог со статическими файлами
location /static/ {
alias /usr/local/share/dj2/static/;
}

# Каталог со статическими файлами для админ-панели Django
location /static/admin/ {
alias /usr/lib/python2.7/dist-packages/django/contrib/admin/static/admin/;
}
Особенность в том, что модификатор в данном случае не используется, а в первой директиве location нужно перечислить все страницы, обработку которых нужно передавать в Django-приложение. Впрочем, если кроме этого приложения на сервере больше ничего нет и не будет, можно создать секцию для обработки корневого каталога.

Осталось перезагрузить или перезапустить nginx.

11. Python и веб-фреймворк Bottle

В случае с фреймворком Bottle всё аналогично Django. Разница лишь в том, что в Bottle нет генератора проекта, а потому создать объект WSGI-приложения придётся самостоятельно. Если же все маршруты вашего проекта определены в приложении по умолчанию, то достаточно в начало головного файла добавить импорт функции app из модуля фреймворка:
from bottle import app
И затем использовать эту функцию для создания экземпляра WSGI-объекта приложения. Для этого создадим файл /etc/uwsgi/apps-enabled/bottle.ini:
[uwsgi]

; Имена рабочих процессов приложения и мастер-процесса
procname = uwsgi-bottle
procname-master = uwsgi-bottle-master

; В пакете на самом деле два плагина - python26 и python27, выбираем плагин python27
plugin = python27
; Каталог приложения
chdir = /usr/local/share/bottle
; Используем файл main.py, в котором есть функция app, возвращающая экземпляр WSGI-приложения
module = main:app()
; Задаём количество рабочих процессов
processes = 2
Запустим рабочие процессы приложения:
# /etc/init.d/uwsgi start bottle
nginx настраивается аналогично одному из примеров для приложений Django, в зависимости от того, будет ли приложение доступно из каталога или из корня URL.

12. О безопасности

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

Пятница, 22 августа

Сообщество ru_perl в LiveJournal: Mojolicious & MongoDB.pm

Доброго времени суток. Какая-то фигня получается, туплю по не знанию.

Дергаю из mongoDB данные, кладу их в stash:

[code]

sub index {
my $self = shift;

my $client = MongoDB::MongoClient->new;
my $db = $client->get_database( 'articles' );
my $coll = $db->get_collection( 'articles' );

my $cursor = $coll->find({author => 'Marlik'});

while (my $row = $cursor->next) {

$self->stash(title => ($row->{title}));
$self->stash(body => ($row->{body}));
$self->stash(author => ($row->{author}));
$self->stash(datetime => ($row->{data}));

}
}
[/code]

Пытаюсь выловить их в шаблоне, предположительно кривым способом:

[code]

% layout 'default';
% title 'Главная';

<% for(1 .. 3){ %>


<%= $title %>

<%= $body %>

<%= $author %> <%= $datetime %>


<% } %>

[/code]

На выходе получаю последнюю запись в БД. Выводится три раза. Мне нужно вывести три последних записи. Что делаю не так? Спасибо.

Четверг, 21 августа

Блог программиста — Perl, Ruby, C#: Использование статики в Catalyst-приложении (плагин Static::Simple)

Мое тестовое catalyst-приложение начинает потихоньку развиваться и приобретать функциональность. Для создания интерфейса администратора я решила использовать jQuery UI и мне потребовалось добавить в шаблоны ссылки на статические файлы. Ссылки были добавлены, каждую из них catalyst попытался обработать и вернул 404. Решив, что с этой проблемой может столкнуться любой начинающий разработчик, решила написать небольшую заметку о […]

Вторник, 19 августа

Блог программиста — Perl, Ruby, C#: Взаимодействие Catalyst-приложения с внешним API. Пример 1

В дальнейшем хотелось бы найти время и рассмотреть несколько примеров взаимодействия Catalyst-приложения с внешними API. Например, API социальных сетей и авторизация с помощью OAuth (особенно заинтересовал Twitter), API платежных систем, API для совершения покупок он-лайн. Ниже — самый простой, односторонний, пример взаимодействия с внешней системой (строго говоря, это даже назвать API нельзя). Приведенный код строится […]

Вторник, 12 августа

Хабрахабр: Метки / perl: Функции в Perl


image

В Perl заложено огромное количество возможностей, которые, на первый взгляд, выглядят лишними, а в неопытных руках могут вообще приводить к появлению багов. Доходит до того, что многие программисты, регулярно пишущие на Perl, даже не подозревают о полном функционале этого языка! Причина этого, как нам кажется, заключается в низком качестве и сомнительном содержании литературы для быстрого старта в области программирования на Perl. Это не касается только книг с Ламой, Альпакой и Верблюдом («Learning Perl», «Intermediate Perl» и «Programming Perl») — мы настоятельно рекомендуем их прочитать.

В этой статье мы хотим подробно рассказать о маленьких хитростях работы с Perl, касающихся необычного использования функций, которые могут пригодится всем, кто интересуется этим языком.
Читать дальше →

Сообщество ru_perl в LiveJournal: Mojolicious templates

Доброго времени суток. Закавыка такая вот получается. Снес по ошибке все данные, пытаюсь восстанавливать по памяти. Речь о шаблонах в Моджо. Сделал сайт, трехколоночный - левый сайдбар, правый сайдбар и собсно контент. Мысль такова, в левом и правом сайдбарах хочу выводить последние записи, последние комментарии и т. д. то есть динамика. Ну а в контенте понятно что <%= content %>. Все это дело в обертке(layout). Сделал несколько страниц, сделал для них роуты, все работает, все отлично, переменные передаются в шаблон. Но в левый и правый сайдбар никак не могу передать переменную. Получается что только статика в сайдбарах может быть? Либо надо думать над роутами, то есть в каждом роуте передавать данные в сайдбары, но это как-то криво имхо. Ни через render, ни через stash ничего не попадает в шаблоны. Либо я туплю, либо уже все спать итить пора.


Спасибо всем кто останется неравнодушным.

Хабрахабр: Метки / perl: [Из песочницы] Автоматизация снятия показаний со счетчиков воды


Все знают, что лень двигатель прогресса. Так случилось и в моем случае.



В квартире присутствует 6 точек раздачи воды (3 холодные и 3 горячие). На каждой из точек стоит счетчик.
Каждые 2 счетчика спрятаны за люками скрытого монтажа, один из люков находится за зеркалом, которое нужно снять, чтобы до него добраться.

Раз в месяц с 20 по 25 число необходимо снимать показания со всех счетчиков и отправлять данные в Управляющую Компанию на бланке определенного образца.

В какой-то момент мне надоело открывать люки, снимать зеркало и было решено автоматизировать снятие показаний.
Читать дальше →

Вторник, 5 августа

Блог программиста — Perl, Ruby, C#: Использование MooseX::Singleton в Catalyst-приложении

Использование MooseX::Singleton в Catalyst-приложении на конкретном примере, при реализации работы с конфигурационными данными. Использование паттерна «Singleton» в Catalyst-приложении. Примеры кода. Примеры использования Class::Accessor. Синтаксис: package MyClass; use MooseX::Singleton; has config => ( is => 'rw' ); package main; use MyClass; my $instance = MyClass->instance; # можно вызвать MyClass->instance еще раз, будет возвращена ссылка # на […]

Воскресенье, 27 июля

koorchik's Perl blog: Фотографии с Perl-хакатона в Киеве (2014)

Четверг, 24 июля

Блог программиста — Perl, Ruby, C#: Ведение логов в Catalyst с помощью Log::Dispatch

Log::Dispatch помогает задать — насколько подробно будет осуществляться логирование. Будут ли выводиться в лог только критические ошибки, или будут включены и отладочные сообщения, или уровень, начиная с не критичных предупреждений. Кроме того, с помощью Log::Dispatch удобно задавать объекты для вывода сообщений. Пример использования Log::Dispatch в Catalyst-приложении Как создать Catalyst-приложение с нуля >> app::Log.pm : package […]

perl | Misc: Качалка видео для Collegehumor

Если вы задаетесь вопросом, почему на блоге ничего нового нет? То всё просто - dx умотал в Сиэтл и вернулся оттуда только на днях, именно поэтому вы еще не видели новый PHP обфускатор, обновление PE Bliss и прочие классные вещи. По приезду dx отправился на свой любимый ресурс, Collegehumor, чтобы посмотреть какое-нибудь смешное видео и, […]

Вторник, 15 июля

Хабрахабр: Метки / perl: Как устроена система SMSDirect


image

Здравствуйте, хабражители!

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

Понедельник, 14 июля

Меркантильный гуру: CTPP

И снова меня мучает вопрос - на что бы перейти с CTPP?

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

Адски нехватает TMPL_macro, и кучи разных мелочей.

При этом сам CTPP сейчас стабилен от слова стабильность и глядя в комитты и открытые тикеты всё ясно.

(для тех, кто меня не знает или не читает, но увидит этот пост в рсс - не надо предлагать TT, ep и прочий треш, особенно если вы не понимаете, почему люди используют CTPP)

upd: и да, не надо предлагать Tenjin. Потому что, для начала, это такой монстр на который вообще непонятно как переходить (хотя там есть плагин для синтаксиса HTML::Template и его, наверное, можно было бы руками допилить), а для конца - судя по странице проекта - там не меньшая стабильность в лучших японских традициях

Пятница, 11 июля

Catalyst - MVC Perl Framework: Содержание

XPoint.ru | Программирование::Perl::Основы: Не равны одинаковые строки

Столкнулся со странной проблемой. Одинаковые строки не равны с точки зрения Perl.
Суть: получаю подпись от платежной формы - это md5_hex-строка в base64. Генерирую ее же в скрипте и просто сравниваю.
Визуально одинаковые строки не проходят проверку if($sign eq $signencoded){}
Почему

'Zjk5NTY0NDExMGI3NTgxNTZhNGYxYzI4YmEwOGZjNTk=' ne
'Zjk5NTY0NDExMGI3NTgxNTZhNGYxYzI4YmEwOGZjNTk='

?

Вторник, 8 июля

Хабрахабр: Метки / perl: Обзор Komodo Edit и Komodo IDE 8


Привет. На хабре много обзоров различных сред разработки, но совсем мало информации про Komodo Edit и Komodo IDE.
Я пользуюсь Komodo с 2010 года и за это время вышло несколько мажорных релизов и хочу с вами поделиться кратким обзором основных возможностей.



Komodo Edit — это кросс-платформенный текстовый редактор, который построен на движке Mozilla, поддерживает большое количество языков. Проект является полностью открытым и распространяется под лицензией MPL (Mozilla Public License). Разработка проекта ведется на GitHub.
Как и у всех, есть авто-дополнение со справочной информацией, поддержка плагинов, макросы, сниппеты.
Главная фича, которая мне понравилась, это удаленное редактирование кода, подобно Sublime если прикрутить к нему плагины для работы по SFTP. В восьмой версии также появился визуальный скроллинг, аналогично тому, который есть в Sublime.

Читать дальше →

Понедельник, 7 июля

Мини-портал Perl на Opennet: Семнадцатый выпуск журнала Pragmatic Perl

Представлен семнадцатый выпуск Pragmatic Perl, русскоязычного журнала о современном языке программирования Perl.

Вторник, 1 июля

Блог программиста — Perl, Ruby, C#: Как нарисовать диаграмму с помощью GD::Graph и perl

Заметки о создании диаграмм с помощью perl и GD::Graph. Примеры кода. Примеры создания диаграмм для фондового рынка. Все примеры протестированы в windows-среде. Я не ставила перед собой цели создать объемное руководство по GD::Graph, поэтому ниже в основном только примеры кода.   Линейные диаграммы Можно выбрать несколько вариантов отрисовки линейных диаграмм: просто линия на графике (модуль […]

Чтобы не искать: Блокировка запуска второго экземпляра программы на Perl

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

Нужно проверить - является ли запускаемый процесс единственным, запущенным в данный момент, экземпляром программы, или уже есть другой, запущенный экземпляр?

Варианты решения

Есть несколько методов такой проверки.

1) Проверка существования пид-файла

Скрипт запускается и проверяет наличие пид-файла. Если пид-файл уже существует - значит, другой экземпляр скрипта уже запущен и второй раз запускаться не следует. Если же пид-файла не существует, то скрипт создает пид-файл и начинает работать.

Проблема в том, что первый экземпляр может упасть, не удалив пид-файл. И теперь запустить скрипт будет вообще невозможно, так как запускаемый скрипт всегда будет обнаруживать пид-файл, считать себя вторым экземпляром и отказываться запускаться, пока пид-файл не будет удален вручную. Кроме того, существует проблема с гонкой условий, так как проверка существования файла и последующее создание этого файла являются двумя отдельными операциями, а не одной атомарной.

2) Проверка наличия пида в списке процессов

Скрипт запускается, читает пид-файл и затем проверяет - есть ли процесс с прочитанным пидом в таблице процессов. Если такой процесс существует - значит, другой экземпляр скрипта уже запущен и второй раз запускаться не следует. Если же такого процесса не существует, то скрипт записывает свой пид в пид-файл и начинает работать.

Проблема в том, что первый экземпляр может упасть, а пид, с которым он работал, может быть выдан другому процессу. После этого, как и в первом методе, возникнет проблема с запуском скрипта. Конечно, вероятность возникновения такой ситуации несколько ниже, чем в первом случае, ведь повторно пид будет выдан не сразу. Да и вероятность того, что посторонний процесс получит точно такой же пид, как и наш процесс, не очень большая, однако она есть, так как пидов не бесконечное количество и они выдаются по кругу. Ну и плюс гонка условий, так как операций тут еще больше, чем в первом методе.

3) Блокировка пид-файла

Скрипт запускается и пытается заблокировать пид-файл. Если заблокировать не удалось - значит, другой экземпляр скрипта уже запущен и второй раз запускаться не следует. Если же заблокировать пид-файл удалось, то скрипт продолжает работать.

Этот метод не имеет проблем, возникающих в предыдущих двух методах:

- Падение первого экземпляра скрипта автоматически снимает блокировку с пид-файла, поэтому следующий экземпляр может быть запущен без проблем
- Не возникает гонка условий, так как блокировка является атомарным действием

Таким образом, этот метод гарантированно обеспечивает блокировку запуска второго экземпляра программы.

Метод блокировки пид-файла

Рассмотрим подробно реализацию этого метода.

#!/usr/bin/perl

use Carp; use Fcntl qw(:DEFAULT :flock);

check_proc('/tmp/testscript.pid') and die "Скрипт уже запущен, запуск дубля отклонен!\n";

# Тут находится код, # который должен исполняться # в единственном экземпляре sleep 15;

# Проверка существования запущенного экземпляра sub check_proc { my ($file) = @_; my $result;

sysopen LOCK, $file, O_RDWR|O_CREAT or croak "Невозможно открыть файл $file: $!";

if ( flock LOCK, LOCK_EX|LOCK_NB ) { truncate LOCK, 0 or croak "Невозможно усечь файл $file: $!";

my $old_fh = select LOCK; $| = 1; select $old_fh;

print LOCK $$; } else { $result = <LOCK>;

if (defined $result) { chomp $result; } else { carp "Отсутствует PID в пид-файле $file"; $result = '0 but true'; } }

return $result; }


В первую очередь скрипт вызывает функцию check_proc, проверяющую наличие другого запущенного экземпляра, и, если проверка завершается успешно, скрипт останавливается с соответствующим сообщением.

Обратите внимание, что в этой строке функции check_proc и die объединены через условный оператор and. Обычно подобные связки делаются через оператор or, но в нашем случае логика связки другая - мы как бы говорим скрипту: "Осознай бессмысленность своего существования и умри!".

Функция check_proc возвращает пид уже запущенного экземпляра, если он действительно запущен, либо undef. Соответственно, истинный результат выполнения этой функции означает, что один экземпляр программы уже запущен и второй раз запускаться не нужно.

Функция check_proc

Теперь разберем построчно саму функцию check_proc.

1) Функция sysopen открывает файл на чтение и запись.

Тут важно то, что файл нужно открывать в неразрушающем режиме, иначе содержимое файла будет уничтожено. Из-за этого нельзя воспользоваться простой функцией open, так как она не умеет открывать файлы в неразрушающем режиме.

Функция sysopen c флагами O_RDWR|O_CREAT открывают файл именно в неразрушающем режиме. Флаг O_RDWR означает открытие одновременно на чтение и запись, флаг O_CREAT создает файл, если его не существует на момент открытия. Флаги импортируются из модуля Fcntl (можно обойтись без Fcntl, если использовать численные значения флагов).

2) Функция flock блокирует файл.

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

Если функция flock обнаруживает, что кто-то другой уже заблокировал файл, то она будет ждать, пока блокировка не будет снята. Такое поведение не подходит для нашей проверки. Нам не нужно ждать освобождения файла, нам нужно, чтобы при обнаружении блокировки функция check_proc сразу вернула положительный результат. Для этого нужно использовать флаг LOCK_NB.

Дальнейшее поведение зависит от того, удалось ли получить блокировку (3) или не удалось (4).

3а) Функция truncate очищает файл.

Поскольку мы открыли файл в неразрушающем режиме, то старое содержимое файла осталось нетронутым. Это содержимое нам не нужно, и даже может мешать, поэтому файл нужно очистить.

3б) Комбинация функций select и переменной $| отключает буферизацию.

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

Чтобы отключить буферизацию вывода, нужно связанную с дескриптором этого вывода переменную $| установить в истинное значение. Первый select устанавливает текущим дескриптором дескриптор нашего пид-файла, затем переменная устанавливается в истинное значение, потом второй select возвращает STDOUT обратно на место текущего дескриптора. После этого запись в файл будет происходить немедленно, без буферизации.

4а) Читаем пид из пид-файла

Само чтение из файла тривиально, но нужно иметь в виду, что возможна ситуация, когда пид в файле не будет обнаружен. Это будет означать, что экземпляр программы уже запущен (ведь блокировку получить не удалось), но пид этого запущенного экземпляра почему-то не записан. Это не должно стать проблемой для нашей проверки, ведь она основана не на проверке пида. Но функция check_proc должна возвращать истинное значение в случае обнаружения запущенного экземпляра, поэтому вместо отсутствующего пида нужно вернуть что-то другое, являющееся, тем не менее, истиной.

Подходящим значением в этом случае будет "истинный ноль". Это магическое значение (которых в перле много), которое в числовом контексте равно нулю, а в булевом равно истине. Вариантов записи истинного ноля несколько, я использую вариант "0 but true".

Заключение

Метод блокировки пид-файла является самым надежным способом обеспечения работы программы в единственном экземпляре.

Функцию check_proc и подключение модуля Fcntl можно вынести в отдельный модуль (например, c названием MacLeod.pm), в этом случае обеспечение работы программы в одном экземпляре будет делаться всего в две строчки:

use MacLeod;

check_proc('/tmp/testscript.pid') and die "Скрипт уже запущен, запуск дубля отклонен!\n";


Либо, проверку можно сделать немного более развернутой:

use MacLeod;

my $pid = check_proc('/tmp/testscript.pid');

if ($pid) { die "Скрипт с пидом $pid уже запущен, запуск дубля отклонен!\n"; } else { print "Поехали!\n"; }


В этом случае возвращаемый функцией check_proc пид запущенного процесса записывается в переменную $pid и его можно вывести в сообщении.

Понедельник, 30 июня

Сообщество ru_perl в LiveJournal: Автоматический перезапуск приложения при разработке на Perl Dancer

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


#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use File::Modified;
use Proc::Background;
use DateTime;
my $proc1 = Proc::Background->new("perl E:/path/to/your/applications/bin/app.pl");
my $d = File::Modified->new(files=>['path/to/your/checked/file/config.yml','path/to/your/checked/file/yourapplication.pm']);

print "status=".$proc1->alive."\n";
while (1) {
  my (@changes) = $d->changed;

      if (@changes) {
      my $dt = DateTime->now;
      $dt->set_time_zone( 'Asia/Irkutsk' );
      print $dt;
print "$_ was changed\n" for @changes;
      print "stopping...\n";
      print "status=".$proc1->die."\n";
      print "starting...\n";
   $proc1 = Proc::Background->new("perl E:/path/to/your/applications/bin/app.pl");
      print "status=".$proc1->alive."\n";
      $d->update();
  };
sleep 1;
};

Хабрахабр: Метки / perl: Документация Mojolicious: Потерянные Главы


Это продолжение серии статей о веб-фреймворке для Perl — Mojolicious: первая часть.

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

Асинхронность: синхронизируем с помощью Mojo::IOLoop::Delay


Mojo::IOLoop::Delay предоставляет механизм, обеспечивающий для асинхронно выполняющихся callback-ов:

  • описание последовательно выполняющихся операций без «лапши» callback-ов
  • передачу результатов из callback-а(ов) текущего шага на следующий
  • общие данные для callback-ов, объединённых в одну задачу
  • синхронизацию групп callback-ов
  • перехват и обработку исключений в callback-ах

Используемые термины:

  • (асинхронная) операция — обычно это вызов асинхронной функции вроде  таймера или выкачивания url, которой необходимо передать callback
  • шаг — callback, который анализирует данные полученные с предыдущего  шага (если это не первый шаг), и запускает одну или несколько новых  операций, либо возвращает финальный результат (если это последний шаг)
  • задача — список шагов, которые должны выполняться последовательно  (т.е. следующий шаг вызывается только после того, как все операции  запущенные на предыдущем шаге завершаются)

Альтернатива Promises

Это альтернативный подход к проблеме, обычно решаемой с помощью Promise/Deferred или Future. Вот приблизительное сравнение со спецификацией Promises/A+Читать дальше →

Пятница, 27 июня

Хабрахабр: Метки / perl: Мониторинг Java приложений в Zabbix, кастомизируем JavaGateway для JMX LLD


Вступление


    В данной статье я расскажу, как можно немного кастомизировать Zabbix JavaGateway для наиболее удобного низко уровневого обнаружения JMX метрик. Здесь github.com/mfocuz/zabbix_plugins/tree/master/jmx_discovery можно взять патч на версию 2.0.11 и посмотреть примеры external скриптов. Но обо всем по порядку.

    С версии 2.0 в Zabbix появилась нативная поддержка мониторинга Java приложений через JMX. Но возможно не все знают, что кроме сбора метрик мы можем их также дискаверить в Zabbix из коробки. В документации этот момент либо пропустили, либо посчитали фичу несовсем готовой(хотя может я просто не нашел этого в доке?), но эта фича там есть, и, на мой взляд, она действительно не совсем готова. Хотя я не уверен что она вообще работает, до тестирования не дошло.
Читать дальше →

Вторник, 24 июня

Хабрахабр: Метки / perl: Документация Mojolicious: Потерянные Главы


Mojolicious — восхитительный современный веб-фреймворк для Perl. Из недостатков я могу назвать только два: политика в отношении обратной совместимости и документация.

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

Содержание


  1. Недостатки
  2. Роутинг: внутреннее устройство
  3. Роутинг: настройка
  4. Параметры HTTP-запроса
  5. Парсинг
  6. Tips & Tricks
    1. Поддержка неблокирующих приложений в режиме CGI
    2. Как работает Mojo::UserAgent при тестировании своего приложения
    3. ojo и Mojolicious::Lite
    4. Переменные окружения


Другие статьи в этой серии



Недостатки


В официальном FAQ написано: "… we will always deprecate a feature before removing or changing it in incompatible ways between major releases … as long as you are not using anything marked experimental, untested or undocumented, you can always count on backwards compatibility …". Для начала, вторая фраза противоречит первой. Далее, вот цитата из Guides::Contributing «Features may only be changed in a major release or after being deprecated for at least 3 months.». Честно говоря, 3 месяца это и так смешной срок когда речь идёт об обратной совместимости, но похоже что даже этот срок соблюдается не всегда (поддержку «X-Forwarded-HTTPS» сделали deprecated два месяца назад, а удалили месяц назад — да, это был «major release» поэтому формально правила не нарушены, но общее отношение к обратной совместимости вполне показательно). Как много разработчиков обновляет фреймворк чаще чем раз в 3 месяца, да ещё и при этом тщательно вычитывает Changes или логи своего приложения на предмет deprecated-предупреждений? При этом, в течении последнего года было deprecated примерно 20 функций/фич. На практике, конечно, всё не так плохо, как это звучит — что-то ломается не так уж часто (лично меня за последний год коснулась только замена $app->secret() на $app->secrets()). Но факт остаётся фактом — обратную совместимость ломают, ломают часто, причём без по-настоящему веских причин: например, в случае с secret() абсолютно ничего не мешало добавить в код
sub secret { shift->secrets([shift]) }

либо просто добавить поддержку дополнительных параметров в secret() вместо добавления новой функции secrets() реализовав нужную фичу вообще не ломая совместимость.

Что касается документации, то многие считают её отличной, даже одним из серьёзных достоинств Mojolicious, но никак не недостатком. Проблема с документацией в том, что она вся сосредоточена на примерах. Это реально круто, когда ты начинаешь изучать фреймворк. Это экономит кучу времени, когда тебе нужно сделать фичу и ты быстро гуглишь пример аналогичной фичи в официальных guides. Но как только ты выходишь за рамки стандартных задач и возникает необходимость понять, как что-то устроено идеологически или архитектурно, какие конкретно параметры может принимать эта функция и что конкретно она может возвращать в разных ситуациях — выясняется, что для многих модулей Mojolicious такая документация отсутствует в принципе. И не потому, что эта информация относится к «недокументированным возможностям» — почти всё это мельком упоминается здесь и там в разных примерах, а значит считается «документированным». Нередко есть несколько способов получить доступ к определённым данным (параметры запроса, тело ответа, etc.) но не описано чем они друг от друга отличаются и в каких ситуациях правильнее пользоваться какими способами. И последнее — алфавитный порядок функций в доке, серьёзно?! Нет, я понимаю, все люди разные и кому-то наверняка это удобно, но многим всё-таки на порядок проще воспринимать документацию в которой функции сгруппированы по задачам. (Хотя в коде, особенно при чтении его через браузер, где не так удобно пользоваться поиском как в Vim, алфавитный порядок функций неожиданно оказался довольно удобным — кроме new/DESTROY/AUTOLOAD — их всё-таки лучше размещать в начале.) В результате, чтобы разобраться приходится вычитывать код (некоторые предпочитают вместо этого смотреть тесты!), что не так просто — во-первых он не является эталоном читабельности: автор любит использовать фишки перла, которые позволяют писать код компактно (и нередко такой код быстрее работает), но читабельность это ухудшает; во-вторых активное использование и наследования и обмена событиями между объектами усложняет понимание того, что и как происходит внутри 104 классов, из которых состоит Mojolicious-5.

С проблемой обратной совместимости мы мало что можем сделать (хотя, наверное, можно сделать плагин к Mojolicious, который будет её эмулировать по мере возможности). Зато вторую проблему решить не сложно — недостающую документацию можно написать самостоятельно. По мере изучения Mojolicious я планирую описывать некоторые вещи, которые, по-хорошему, должны быть в официальной документации, отсюда и название этой статьи.
Читать дальше →

Пятница, 13 июня

Laziness, Impatience and Hubris: COW in perl-5.20

В perl-5.20 реализовали механизм копирования при записи (copy-on-write) для строк. Теперь при присвоении одному скаляру значения другого, копирования буфера строки сразу не происходит. Это значительно повышает производительность и снимает необходимость передачи аргументов функций по ссылке (если они не будут изменяться).

Сравним скорость вызова подпрограмм с различными комбинация передачи параметра и возвращения результата для предыдущей версии perl и для версии с COW:
> perlbrew use perl-5.18.2
> perl ref_and_val.pl
Rate val -> val val -> ref ref -> val ref -> ref
val -> val 68213/s -- -51% -51% -97%
val -> ref 138122/s 102% -- -1% -93%
ref -> val 139276/s 104% 1% -- -93%
ref -> ref 2000000/s 2832% 1348% 1336% --

> perlbrew use perl-5.20.0
> perl ref_and_val.pl
(warning: too few iterations for a reliable count)
(warning: too few iterations for a reliable count)
(warning: too few iterations for a reliable count)
Rate ref -> val val -> val ref -> ref val -> ref
ref -> val 2083333/s -- -17% -21% -29%
val -> val 2500000/s 20% -- -5% -15%
ref -> ref 2631579/s 26% 5% -- -11%
val -> ref 2941176/s 41% 18% 12% --
Результаты впечатляют, так как длина тестируемой строки 100000 символов!

А теперь возьмем реальное приложение. Оно сетевое, занимается "перекладыванием байтиков" с одного источника в 4 на основе srs32.
Ниже приведены количество запрос в секунду для 3 различных типов запросов в простом и pipeline режимах. Уточнение: сеть не является узким местом.
                 1     2     3
perl-5.14.4 7272 6134 3886
perl-5.18.2 7610 6439 4139
perl-5.20.0 7581 6459 4338

pipeline mode:
perl-5.14.4 21141 13869 5998
perl-5.18.2 21367 14025 6269
perl-5.20.0 21598 14367 6518
Как видим, в реальном приложении выигрыш от COW не заметен.

Вторник, 10 июня

Ловушки Perl: Задачи-страшилки про Perl: Однострочная фильтрация

В файле хранится статистика по частоте слов в некотором тексте:

    > head -n 20 file.in
      1 printed
      1 sole
      5 open
      4 separate
      1 almost
     10 some
      2 entire
      1 preferred
      1 theargument
      5 sysv
     47 foo
    116 to
      2 very
      1 archaic
     48 not
      8 returns
      1 crudely
     10 function
      1 conversion
      9 must

  

Программисту понадобилось отобрать слова, встречающиеся 10 раз и чаще, и при этом длиной от 3 до 8 символов включительно.

Получился вот такой однострочник:

    > cat file.in | perl -ape 'next if $F[0] < 10; $l = length($F[1]); next if ($l<3||$l>8);' > file.out

  

Но все пошло не так, как рассчитывал программист…

Пятница, 6 июня

Сообщество ru_perl в LiveJournal: Log::Log4perl и semget

Пример из CPAN, один в один:

use Log::Log4perl;

my $conf = qq ( log4perl.category = INFO, Syncer # File appender (unsynchronized) log4perl.appender.Logfile = Log::Log4perl::Appender::File log4perl.appender.Logfile.autoflush = 1 log4perl.appender.Logfile.filename = ./test.log log4perl.appender.Logfile.mode = truncate log4perl.appender.Logfile.layout = SimpleLayout # Synchronizing appender, using the file appender above log4perl.appender.Syncer = Log::Log4perl::Appender::Synchronized log4perl.appender.Syncer.appender = Logfile );

Log::Log4perl->init(\$conf);



Результат:
semget(1882483807) failed:  at /usr/share/perl5/Log/Log4perl/Util/Semaphore.pm line 64.

Ы?

Среда, 4 июня

Мини-портал Perl на Opennet: Представлен Perl::Lint, статический анализатор кода для языка Perl

В рамках проекта Perl::Lint началась работа по созданию статического анализатора исходных текстов на языке Perl, позволяющего выполнять проверку корректности кода, без его выполнения. Основным отличием от уже существующих анализаторов, таких как Perl-Critic, является очень высокая скорость проверки кода, дающая возможность проверять код в режиме реального времени, что позволяет использовать Perl::Lint для информирования об ошибках по мере написания кода в редакторах и интегрированных средах разработки. Ускорение достигается за счёт применения для разбора кода модулей Compiler::Lexer и Compiler::Parser, вместо PPI. Работа ведётся по гранту организации Perl Foundation и завершена на 30%.

Среда, 28 мая

Меркантильный гуру: perl 5.20

Вышел perl 5.20. У кого-то сверкнуло просветление в голове и теперь можно удобно получать переменные в функциях.

Теперь Function::Parameters не нужен (а я все ломаю голову как заставить Sublime нормально поддерживать его синтаксис). Хотя синтаксически оно все равно не идеально - теперь есть пересечение со старым способоом задания необходимых и опциональных переменных при вызове функции и один способ не полностью соответствует другому (в терминах перла - сигнатуры функций и прототипы). Вот это вот вообще прелестно: "To avoid ambiguity, when signatures are enabled the special syntax for prototypes is disabled.".

Постфиксное разыменование - тоже хорошая штука, но с таким синтаксисом код станет только страшнее.

Остальное не так критично, просто в мелочах сделали немного лучше. Пожалуй, подожду 5.20.1 и попробую в продакшене на это перейти (сейчас у нас везде 5.14).

Вторник, 27 мая

Мини-портал Perl на Opennet: Релиз интерпретатора языка программирования Perl 5.20

После года разработки представлена новая стабильная ветка языка программирования Perl - 5.20. При подготовке нового выпуска было изменено около 470 тыс. строк кода, изменения затронули 2900 файлов, в разработке приняли участие 124 разработчика.

Вторник, 20 мая

crux's blog: Протокол HTTP/2 и его реализация

Работа над новым протоколом для всемирной сети находится на завершающем этапе. HTTP/2 должен решить многие застарелые проблемы HTTP/1.1 и дать возможность Интернету развиваться дальше. Есть довольно хорошая статья «http2 explained» , посвященная новому протоколу HTTP/2, разъясняющая предпосылки его создания и наглядно демонстрирующая его возможности и принципы работы. Статья, тем не менее, не содержит какой-либо детальной технической спецификации протокола. Есть также отличная книга Ilya Grigorik «High-Performance Browser Networking» , веб-версия которой свободно доступна , и которая также содержит интересные детали о прародителе HTTP/2 - SPDY и самом HTTP/2 (правда уже немного устаревшие). После её прочтения я вдохновился создать реализацию HTTP/2-протокола и в процессе досконально изучить новый протокол. Эта статья - небольшой отчёт за последние два месяца убитого свободного времени.
Комментарии(0)

Пятница, 16 мая

Хабрахабр: Метки / perl: Право на свой код


Германская консервативная система ценностей определяла социальную роль женщины тремя «К»: Kinder, Küche, Kirche (дети, кухня, церковь). Как это ни странно, но атавизмы того времени живы и по сей день – многие профессии традиционно считаются чисто мужскими, и сломить эту идеологическую преграду удаётся не многим.

Далеко ходить не надо, соотношение женского пола к мужскому среди жителей Хабрахабра – меньше чем 1 к 10 (На момент написания поста — 101448 мужчин против 7772 женщин).

Большая часть ИТ-коллективов похожа на мужской монастырь. Девушки встречаются в рекламе, маркетинге, чуть реже в дизайне и графике, но совсем редко в «святая святых» – в программировании.

В большом коллективе Mail.Ru девушек тоже не так много, но они есть. И у одной из них – Екатерины Трефиловой lecharton– разработчика из Афиши Mail.Ru, мы решили взять небольшое интервью.

Читать дальше →

Четверг, 15 мая

Сообщество ru_perl в LiveJournal: Ищу работу

Удалённо, фуллтайм, с белой зарплатой и оформлением.

Вторник, 13 мая

Записки программиста — Perl: Ломаем капчу — сбор данных и их предварительный анализ

Итак, мы с вами полны решимости сломать какую-нибудь капчу. С одной стороны, капча не должна быть слишком простой или уже кем-то сломанной, потому что так не интересно. С другой, выбрав слишком сложную капчу можно потратить кучу времени на ее взлом и не добиться никакого результата. Также желательно, чтобы капча использовалась на каком-нибудь более-менее известном сайте, [...]

Понедельник, 12 мая

Записки программиста — Perl: Астрологи объявили неделю взлома капчи

У каждого из нас, само собой разумеется, есть богатейший опыт распознавания капч. Капчи бывают разные — всевозможные логические («кликните на синий кружочек», «на каких картинках изображены котята?» и так далее), звуковые, есть даже капчи, предлагающие выбрать самую красивую фотографию. Но самыми распространенными на сегодняшний день остаются капчи с искаженным изображением букв и/или цифр. На этой [...]

Среда, 7 мая

Сообщество ru_perl в LiveJournal: Загрузка модуля после запуска скрипта

Добрый день!
Задача следующая.
Запускается скриптy на перле, примерно так :
test_run.pl -test test1
test_run.pl -test test2
-------
test_run.pl -test testN
ну и так далее.
test1,test2,...,testN - тесты, написанные на перле и запускаемые из test_run.pl.
Хотелось бы,чтобы они (тесты) были реализованы в виде модулей и запускались без system call.

Вопрос. Как сделать так,чтобы в теле основной программы было бы написано что-то вроде
use $test;
И переменная test определялась бы соответствующим параметром командной строки после запуска test_run.pl?

Вторник, 6 мая

Мини-портал Perl на Opennet: Пятнадцатый выпуск журнала Pragmatic Perl

Представлен пятнадцатый выпуск Pragmatic Perl, русскоязычного электронного журнала о современном языке программирования Perl.

Мета

Поиск

Участники

Список участников в формате OPML OPML

Добавить сайт

По-другому

Приборы