вторник, 11 декабря 2007 г.

Активация windows и http прокси

Решение проблемы активации операционных систем семейства windows при использовании http прокси сервера squid, требующего авторизации пользователей.

Я никогда не работал с лицензионной ОС windows. Раньше была ворованная, теперь уже 2 года как я не использую windows совсем, ни дома, ни на работе. Но возникла задача: в организации не могут активировать свой легально купленный экземпляр windows через интернет. Доступ к интернет осуществляется через http прокси сервер squid, требующий авторизацию пользователей.

Гугление дает описание этой ошибки в базе данных глюков, которую сама микрософт почему-то называет «базой знаний». Предлагается на выбор 3 варианта костылей:

  1. Отказаться от авторизации пользователей на http-прокси сервере.
  2. Задать список урлов, не требующих авторизации:

    • http://go.microsoft.com/*
    • https://sls.microsoft.com/*
    • https://sls.microsoft.com:443
    • http://crl.microsoft.com/pki/crl/products/MicrosoftRootAuthority.crl
    • http://crl.microsoft.com/pki/crl/products/MicrosoftProductSecureCommunications.crl
    • http://www.microsoft.com/pki/crl/products/MicrosoftProductSecureCommunications.crl
    • http://crl.microsoft.com/pki/crl/products/MicrosoftProductSecureServer.crl
    • http://www.microsoft.com/pki/crl/products/MicrosoftProductSecureServer.crl
  3. Активировать копию windows по телефону.

Для решения проблемы используем костыль №2. Добавляем следующие строки в файл конфигурации squid — /etc/squid/squid.conf

acl micro_act dstdom_regex microsoft\.com$
http_access allow micro_act

После перезапуска squid разрешит обращаться к сайтам, имя которых оканчивается на microsoft.com, не требуя авторизации. Это позволит провести активацию windows, правда учета трафика на эти сайты уже не будет. Это зло, с которым придется смириться. Вот уж не предполагал, что использование легального программного обеспечения создает дополнительные трудности пользователям.

понедельник, 5 ноября 2007 г.

Сравнение производительности perl кода

Иногда требуется выяснить как быстро работает тот или иной фрагмент кода на perl. Для этого можно использовать perl модуль Benchmark, входящий в стандартную поставку perl.

Задача. Как оптимальнее организовать перебор элементов хеша, например просуммировать значения всех ключей. В полном соответствии с принципом TIMTOWTDI существует несколько вариантов решения задачи:

Вариант №1. Использование цикла «foreach ( values ... )».

sub hash_values_sum_1(%) {
    my %hash = @_;
    my $sum = 0;
    $sum += $_ foreach values %hash;
    return $sum;
}

Вариант №2. Использование конструкции«map ... values ... ».

sub hash_values_sum_2(%) {
    my %hash = @_;
    my $sum = 0;
    map { $sum += $_ } values %hash;
    return $sum;
}

Вариант №3. Использование цикла «while ( ... each ... )».

sub hash_values_sum_3(%) {
    my %hash = @_;
    my $sum = 0;
    $sum += $_ while (undef, $_) = each %hash;
    return $sum;
}

Для проверки проверки напишем небольшой тестовый скрипт:

#!/usr/bin/perl -w
use strict;
use Benchmark qw/ :all /;

my %hash = map { rand, rand } ( 1 .. 1000 );

cmpthese( 5_000_000 , {
    var1 => 'my $sum = 0; $sum += $_ foreach values %hash',
    var2 => 'my $sum = 0; map { $sum += $_ } values %hash;',
    var3 => 'my $sum = 0; $sum += $_ while (undef, $_) = each %hash;',
} );

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

          Rate variant_1 variant_3 variant_2
var1  946970/s        --      -48%      -73%
var3 1838235/s       94%        --      -48%
var2 3546099/s      274%       93%        --

По таблице результатов видно, что:

  1. Вариант №3 работает почти в 2 раза быстрее, чем вариант №1.
  2. Вариант №2 работает почти в 2 раза быстрее, чем вариант №3.

В данном конкретном случае вариант №2 является однозначным победителем. Его использование более предпочтительно.

пятница, 19 октября 2007 г.

Пересборка пакетов Slackware

Иногда приходится пересобирать стандартные пакеты Slackware. Зачем? Причины могут быть разные, но чаще всего из-за того, что в стандартной сборке не указаны необходимые опции компиляции.

Пример 1. Вплоть до Slackware 12 так были вынуждены делать все, кому требовался интерпретатор языка perl с поддержкой многопоточности.
Пример 2. Не так давно я радовался, что в Slackware 12 включен пакет для создания шифрованных туннелей openvpn. К сожалению, когда дело дошло до практики мне он оказался совершенно бесполезен без возможности чтения пароля из файла. Опция конфигурации «auth-user-pass /path/to/file» и отвечает за это параметр компиляции «--enable-password-safe».

Сборка пакетов в Slackware осуществляется с помощью так называемых SlackBuild скриптов. SlackBuild скрипт — это обычный shell-скрипт, который осуществляет распаковку архива исходного кода программы, возможно наложение патчей, конфигурирование, компиляцию и запаковку в пакет Slackware. Все SlackBuild скрипты для стандартных пакетов Slackware открыты для свободного доступа и могут быть получены по адресу ftp://ftp.slackware.com/pub/slackware/slackware-<version>/source/, где <version> — это требуемая версия Slackware, одно из «8.1», «9.0», «9.1», «10.0», «10.1», «10.2», «11.0» или «12.0».

Рассмотрим подробнее процесс пересборки стандартного пакета Slackware на примере пакета openvpn. Сначала выкачиваем всё необходимое для сборки:

root@darkstar:~# mkdir /usr/src/openvpn; cd /usr/src/openvpn
root@darkstar:/usr/src/openvpn# wget --recursive --no-directories \
> ftp://ftp.slackware.com/pub/slackware/slackware-12.0/source/n/openvpn
...

root@darkstar:/usr/src/openvpn# ls -la
total 681
drwxr-xr-x 2 root root    264 2007-10-19 08:32 ./
drwxr-xr-x 6 root root    184 2007-10-19 08:30 ../
-rw-r--r-- 1 root root   1375 2007-06-10 01:25 README
-rw-r--r-- 1 root root 669076 2006-10-01 00:00 openvpn-2.0.9.tar.gz
-rw-r--r-- 1 root root    189 2006-10-01 00:00 openvpn-2.0.9.tar.gz.asc
-rw-r--r-- 1 root root   3729 2007-06-12 04:09 openvpn.SlackBuild
-rw-r--r-- 1 root root   6942 2007-06-12 03:48 openvpn.conf.sample
-rw-r--r-- 1 root root    888 2007-06-10 01:23 slack-desc

Прежде всего здесь нас интересует файл openvpn.SlackBuild. Применим следующий патч:

@@ -23,8 +23,8 @@
 VERSION=2.0.9
 ARCH=${ARCH:-i486}
 BUILD=${BUILD:-1}
-#TAG=${TAG:-_SBo}
-unset TAG
+TAG=${TAG:-_SBo}
+# unset TAG
 CWD=`pwd`
 TMP=${TMP:-/tmp}
 PKG=$TMP/pkg-$PRGNAM
@@ -60,6 +60,7 @@
   --sysconfdir=/etc/openvpn \
   --localstatedir=/var \
   --enable-lzo \
+  --enable-password-safe \
   --build=$ARCH-slackware-linux
 
 make || exit 1

Внесенные изменения:

  1. Включена поддержка поля TAG в наименовании пакета. TAG — это идентификатор создателя пакета, добавляется в самом конце имени файла, после номера сборки. В стандартных пакетах отсутствует, а в дополнительно устанавливаемых крайне желателен.
  2. Добавлена опция конфигурирования «--enable-password-safe», то, собственно ради чего вся пересборка и затевается.

Запускаем процесс пересборки пакета:

root@darkstar:/usr/src/openvpn# chmod +x openvpn.SlackBuild
root@darkstar:/usr/src/openvpn# TAG=nmu OUTPUT=`pwd` ./openvpn.SlackBuild
...

root@darkstar:/usr/src/openvpn# ls -la *.tgz
-rw-r--r-- 1 root root 316375 2007-10-18 17:39 openvpn-2.0.9-i486-1nmu.tgz

Если все прошло без ошибок в текущей директории получим файл openvpn-2.0.9-i486-1nmu.tgz. Обновить уже установленный пакет можно с помощью команды:

root@darkstar:/usr/src/openvpn# upgradepkg openvpn-2.0.9-i486-1nmu.tgz

+==============================================================================
| Upgrading openvpn-2.0.9-i486-1 package using ./openvpn-2.0.9-i486-1nmu.tgz
+==============================================================================

Pre-installing package openvpn-2.0.9-i486-1nmu...

Removing package /var/log/packages/openvpn-2.0.9-i486-1-upgraded-2007-10-18,17:44:08...

Installing package openvpn-2.0.9-i486-1nmu... 
PACKAGE DESCRIPTION:
openvpn: openvpn (secure IP tunnel daemon)
openvpn:
openvpn: OpenVPN is a full-featured SSL VPN which can accomodate a wide range
openvpn: of configurations, including remote access, site-to-site VPNs, WiFi
openvpn: security, and enterprise-scale remote access with load balancing,
openvpn: failover, and fine-grained access-controls.
openvpn:
openvpn: OpenVPN's home on the net is:  http://openvpn.net
openvpn:
Executing install script for openvpn-2.0.9-i486-1nmu...

Package openvpn-2.0.9-i486-1 upgraded with new package ./openvpn-2.0.9-i486-1nmu.tgz.

Все, стандартный пакет Slackware пересобран с необходимыми нам опциями и успешно установлен в системе. Вообще изучение стандартных SlackBuild скриптов это хорошая отправная точка для написания собственных. В конце пара ссылок:

http://www.linuxpackages.net/howto.php
Документация по сборке пакетов для Slackware.
http://www.slackbuilds.org
Репозитарий SlackBuild скриптов для многих программ, официально не входящих в дистрибутив.

четверг, 20 сентября 2007 г.

Поиск в Google Maps

Врядли кто-то из жителей Комсомольска-на-Амуре знает где находится улица Путейская. Конечно кроме непосредственно живущих на ней :-). Когда мне там что-то понадобилось, блиц-опрос окружающих ничего не дал. Как ни странно, в итоге мне помог интернет, а конкретно поиск на сервисе Google Maps. Достаточно было в поисковую строку ввести фразу «Комсомольск-на-Амуре, ул. Путейская» и сразу получил карту города отцентрованную на искомой улице. А также возможнось встроить фрагмент карты в веб-страничку, чем здесь и воспользовался:


Просмотреть увеличенную карту

А улица Путейская оказалась в той ещё жопе, не удивительно что раньше я про неё не слышал.

понедельник, 3 сентября 2007 г.

Catalyst, HTTP авторизация и FastCGI

Описанный ранее способ использования http-авторизации в Catalyst проектах упорно не хотел работать с FastCGI протоколом. Использовалось:

  1. Веб-сервер apache версии 2.2.x.
  2. Модуль подержки протокола FactCGI для веб-сервера apache — mod_fascgi версии 2.4.2. Кстати, mod_fastcgi для apache 2.2 без небольшого патча не собирается. Смотри здесь.
  3. Движок Catalyst для обработки запросов по протоколу FastCGI — Catalyst::Engine::FastCGI.

В итоге оказалось две причины:

  1. По протоколу CGI http-заголовок Authorization должен передаваться внешнему приложению в качестве одноименной переменной окружения. Почему-то модуль mod_fastcgi по-умолчанию этого не делает, однако предусматривает специальную опцию -pass-header при передаче запроса FastCGI обработчику. Пример использования в файле конфигурации apache — httpd.conf:

    FastCgiServer                           \
        /root/MyApp/script/myapp_fastcgi.pl \
        -pass-header Authorization
  2. После этого стала доступна переменная окружения Authorization, однако плугин Authentication::Credential::HTTP всё ещё не работал! Дальше пришлось залезть в исходники библиотек Catalyst. Ошибка обнаружилась не в движке Catalyst::Engine::FastCGI, а в его базовом классе Catalyst::Engine::CGI. Из чего с увереностью можно сказать, что и движок Catalyst::Engine::CGI некорректно работает с http-авторизацией. После внесения следующих исправлений всё встало на свои места:

    @@ -95,7 +95,7 @@
     
         # Read headers from %ENV
         while ( my ( $header, $value ) = each %ENV ) {
    -        next unless $header =~ /^(?:HTTP|CONTENT|COOKIE)/i;
    +        next unless $header =~ /^(?:HTTP|CONTENT|COOKIE|Authorization)/i;
             ( my $field = $header ) =~ s/^HTTPS?_//;
             $c->req->headers->header( $field => $value );
         }

На моё сообщение в список рассылки Catalyst не последовало никакой реакции и ошибка сохраняется до сих пор — версия Catalyst::Runtime 5.7010 на текущий момент.

среда, 29 августа 2007 г.

HTTP-авторизация и Catalyst

Протокол HTTP предоставляет возможность авторизации пользователя по имени и паролю. Вкратце схема работы выглядит так:

  1. Веб-браузер посылает обычный http-запрос на доступ к запороленному ресурсу на веб-сервере. Пример:

    GET / HTTP/1.1
    ...
  2. Веб-сервер или веб-приложение формируют http-ответ с кодом 401 и требованием авторизации. Пример basic авторизации:

    HTTP/1.0 401 Unauthorized
    WWW-Authenticate: Basic realm="need authorization"
    ...
  3. Веб-браузер отображает окно авторизации. Например так:

    И после ввода данных посылает второй запрос к веб-ресурсу, содержащий base64-кодированный заголовок Authorization:

    GET / HTTP/1.1
    Authorization: Basic YWRtaW46c2VjcmV0
    ...
  4. Веб-приложение проверяет правильность имени и пароля. Если проверка успешна, выдает нормальный http-ответ:

    HTTP/1.0 200 OK
    ...

    Если проверка не успешна, то повторяется http-ответ с кодом 401. При этом в теле http-ответа уже может содержаться дополнительная информация, объясняющая причину отказа.

Про http-авторизацию можно почитать в rfc 2068. Или в русском переводе этого rfc. Механизм http-авторизации не лишен недостатков. Подробно они описаны в статье «Базовая HTTP-авторизация — защита от честных людей» Алексея Мичурина, опубликованной в журнале «Системный администратор» №5 за 2005 г.

Мы рассмотрим использование http-авторизации c perl веб-фреймворком Catalyst. Для Catalyst существует плугин Catalyst::Plugin::Authentication реализующий основу любой авторизации. Но чтобы его использовать нужны ещё два плугина:

  1. Credential — метод получения информации о пользователе. Доступны такие:

    • Password — авторизация по логину и паролю полученному, например, через веб-форму.
    • HTTP — получение информации о пользователе через http-авторизацию. Именно этим плугином и воспользуемся.
    • Прочие.
  2. Store — способ хранения и проверки полученной информации. Возможные хранилища:

    • DBIC — хранение информации о пользователях в базе данных, с доступом к ней через ORM, например DBIx::Class.
    • Htpasswd — излечение информации из htpasswd файлов, создаваемых одноименной утилитой, входящей в комплект веб-сервера apache. Воспользуемся этим плугином.
    • Minimal — данные о пользователях хранятся внутри конфигурации Catalyst-проекта.
    • Прочие.

Итак, нам будут нужны следующие установленные perl-модули, естественно, со всеми зависимостями:

  • Catalyst::Devel
  • Catalyst::Plugin::Authentication
  • Catalyst::Plugin::Authentication::Credential::HTTP
  • Catalyst::Plugin::Authentication::Store::Htpasswd

Создаем заготовку проекта на фреймворке Catalyst с названием MyApp.

root@darkstar:~# catalyst.pl MyApp
created "MyApp"
created "MyApp/script"
created "MyApp/lib"
created "MyApp/root"
created "MyApp/root/static"
created "MyApp/root/static/images"
created "MyApp/t"
created "MyApp/lib/MyApp"
created "MyApp/lib/MyApp/Model"
created "MyApp/lib/MyApp/View"
created "MyApp/lib/MyApp/Controller"
created "MyApp/myapp.yml"
created "MyApp/lib/MyApp.pm"
created "MyApp/lib/MyApp/Controller/Root.pm"
created "MyApp/README"
created "MyApp/Changes"
created "MyApp/t/01app.t"
created "MyApp/t/02pod.t"
created "MyApp/t/03podcoverage.t"
created "MyApp/root/static/images/catalyst_logo.png"
created "MyApp/root/static/images/btn_120x50_built.png"
created "MyApp/root/static/images/btn_120x50_built_shadow.png"
created "MyApp/root/static/images/btn_120x50_powered.png"
created "MyApp/root/static/images/btn_120x50_powered_shadow.png"
created "MyApp/root/static/images/btn_88x31_built.png"
created "MyApp/root/static/images/btn_88x31_built_shadow.png"
created "MyApp/root/static/images/btn_88x31_powered.png"
created "MyApp/root/static/images/btn_88x31_powered_shadow.png"
created "MyApp/root/favicon.ico"
created "MyApp/Makefile.PL"
created "MyApp/script/myapp_cgi.pl"
created "MyApp/script/myapp_fastcgi.pl"
created "MyApp/script/myapp_server.pl"
created "MyApp/script/myapp_test.pl"

Чтобы убедится что всё прошло успешно, запустим проект на встроенном в Catalyst тестовом веб-сервере.

root@darkstar:~# MyApp/script/myapp_server.pl
[debug] Debug messages enabled
[debug] Loaded plugins:
.----------------------------------------------------------------------------.
| Catalyst::Plugin::ConfigLoader  0.14                                       |
| Catalyst::Plugin::Static::Simple  0.19                                     |
'----------------------------------------------------------------------------'

[debug] Loaded dispatcher "Catalyst::Dispatcher"
[debug] Loaded engine "Catalyst::Engine::HTTP"
[debug] Found home "/root/MyApp"
[debug] Loaded Config "/root/MyApp/myapp.yml"
[debug] Loaded components:
.-----------------------------------------------------------------+----------.
| Class                                                           | Type     |
+-----------------------------------------------------------------+----------+
| MyApp::Controller::Root                                         | instance |
'-----------------------------------------------------------------+----------'

[debug] Loaded Private actions:
.----------------------+--------------------------------------+--------------.
| Private              | Class                                | Method       |
+----------------------+--------------------------------------+--------------+
| /default             | MyApp::Controller::Root              | default      |
| /end                 | MyApp::Controller::Root              | end          |
'----------------------+--------------------------------------+--------------'

[info] MyApp powered by Catalyst 5.7007
You can connect to your server at http://darkstar:3000

Как видно, всё замечательно работает. Теперь мы можем обращаться на 3000 порт тестового сервера из браузера и видеть приветственную заставку по умолчанию.

Начинаем прикручивать http-авторизацию. Открываем основной модуль приложения /MyApp/lib/MyApp.pm, находим строчку, отвечающую за загрузку плугинов:

use Catalyst qw/-Debug ConfigLoader Static::Simple/;

И меняем её на:

use Catalyst qw/
    -Debug

    ConfigLoader
    Static::Simple

    Authentication
    Authentication::Store::Htpasswd
    Authentication::Credential::HTTP
/;

Добавляя таким образом загрузку необходимых плугинов авторизации. Теперь изменим файл конфигурации проекта. Открываем /MyApp/myapp.yml и вставляем следующие строчки:

---
name: MyApp

authentication:
  htpasswd: /root/MyApp/myapp.htpasswd
  http:
    type: basic

Это файл в странном формате YAML, так что соблюдение всех отступов обязательно. Зато он людьми воспринимается легче чем, например, XML. Желающие изучить вопрос могут начать с последней версии YAML спецификации :-) . Для проверки синтаксиса *.yml файла можно использовать утилиту ysh из perl модуля YAML.pm:

root@darkstar:~# cat MyApp/myapp.yml | ysh
$VAR1 = {
  'name' => 'MyApp',
  'authentication' => {
    'htpasswd' => '/root/MyApp/myapp.htpasswd',
    'http' => {
      'type' => 'basic'
    }
  }
};

Если проверка завершается успешно, то на выходе видим соответствующую perl структуру данных. Далее создаем htpasswd файл:

root@darkstar:~# htpasswd -c /root/MyApp/myapp.htpasswd admin
New password:
Re-type new password:
Adding password for user admin
root@darkstar:~# cat /root/MyApp/myapp.htpasswd
admin:mLT84dDiy3H7U

Теперь для авторизированного доступа к определенному action в него достаточно добавить одну строчку кода. Например для доступа ко всем action контроллера Root.pm используем специальный action — auto. Добавим следующие строчки к файлу MyApp/lib/MyApp/Controller/Root.pm:

sub auto : Private {
    my ( $self, $c ) = @_;
    $c->authorization_required( realm => 'catalyst http authorization' );
}

Всё, задача выполнена. Опять запускаем тестовый web-сервер:

root@darkstar:~# MyApp/script/myapp_server.pl
[debug] Debug messages enabled
[debug] Loaded plugins:
.----------------------------------------------------------------------------.
| Catalyst::Plugin::Authentication  0.10002                                  |
| Catalyst::Plugin::Authentication::Credential::HTTP  0.09                   |
| Catalyst::Plugin::Authentication::Store::Htpasswd  0.02                    |
| Catalyst::Plugin::ConfigLoader  0.14                                       |
| Catalyst::Plugin::Static::Simple  0.19                                     |
'----------------------------------------------------------------------------'

[debug] Loaded dispatcher "Catalyst::Dispatcher"
[debug] Loaded engine "Catalyst::Engine::HTTP"
[debug] Found home "/root/MyApp"
[debug] Loaded Config "/root/MyApp/myapp.yml"
[debug] Loaded components:
.-----------------------------------------------------------------+----------.
| Class                                                           | Type     |
+-----------------------------------------------------------------+----------+
| MyApp::Controller::Root                                         | instance |
'-----------------------------------------------------------------+----------'

[debug] Loaded Private actions:
.----------------------+--------------------------------------+--------------.
| Private              | Class                                | Method       |
+----------------------+--------------------------------------+--------------+
| /default             | MyApp::Controller::Root              | default      |
| /end                 | MyApp::Controller::Root              | end          |
| /auto                | MyApp::Controller::Root              | auto         |
'----------------------+--------------------------------------+--------------'

[info] MyApp powered by Catalyst 5.7007
You can connect to your server at http://darkstar:3000

Обратите внимание на лог обработки http-запросов:

[info] *** Request 1 (0.143/s) [5722] [Wed Aug 29 12:52:36 2007] ***
[debug] "GET" request for "/" from "172.16.197.1"
[debug] Checking http basic authentication.
[info] Request took 0.015420s (64.851/s)
.----------------------------------------------------------------+-----------.
| Action                                                         | Time      |
+----------------------------------------------------------------+-----------+
| /auto                                                          | 0.002696s |
| /end                                                           | 0.000278s |
'----------------------------------------------------------------+-----------'

[info] *** Request 2 (0.125/s) [5722] [Wed Aug 29 12:52:45 2007] ***
[debug] "GET" request for "/" from "172.16.197.1"
[debug] Checking http basic authentication.
[debug] Successfully authenticated user 'admin'.
[info] Request took 0.025378s (39.404/s)
.----------------------------------------------------------------+-----------.
| Action                                                         | Time      |
+----------------------------------------------------------------+-----------+
| /auto                                                          | 0.013852s |
| /default                                                       | 0.001557s |
| /end                                                           | 0.000250s |
'----------------------------------------------------------------+-----------'

Первый запрос «Request 1» ещё не содержит информации об авторизации. Action обработчик default так и не был выполнен. Запрос «Request 2» уже содержит заполненный http-заголовок Authorization. По этим данным успешно авторизуется пользователь admin. Управление передается action-у, отвечающему за запрошенный урл — default.

Фактически всё программирование свелось к написанию одной строчки кода. Все остальные действия это установка perl-модулей, внесение изменений в существующие конфигурационные файлы и создание новых конфигурационных файлов. Т.е. это действия системного администратора, а не программиста. Это есть одна из основных и моя самая любимая черта веб-фреймворка Catalyst.

четверг, 2 августа 2007 г.

Правильная установка perl модулей в Slackware

Способ описанный в статье «Установка perl модулей» прекрасно работает. Но пользоваться им, значит идти в обход пакетной системы дистрибутива, что влечет следующие недостатки:

  1. Невозможность удалить perl модуль. CPAN.pm только обещает эти возможности в будущем.
  2. Некорректное обновление модулей. При установке новой версии модуля поверх старой, если должны быть удалены некоторые файлы из старой версии, этого сделано не будет. В лучшем случае это означает мусор в файловой системе, в худшем различные неприятные побочные эффекты.
  3. Невозможность получить список уже установленных модулей.
  4. Замусоривание файловой системы, невозможность определить какой файл к какой программе относится.

Предварительная сборка tgz пакетов Slackware позволяет устранить все вышеперечисленные недостатки. Кроме того, сборку пакетов можно производить не на рабочем сервере, а на отдельной машине, например виртуальной. Что в свою очередь даёт преимущества:

  1. Отсутствует необходимость в средствах сборки на рабочем сервере: make, компилятор, линковщик и т.д. Это экономит место на диске сервера и делает его более безопасным.
  2. Экономия времени, если рабочих серверов больше одного. Однажды собранные пакеты можно установить на много серверов. Установка готового пакета занимает секунды, сборка модуля длится гораздо дольше.

Переходим к практической части. Вначале необходимо сконфигурировать утилиту cpan, как написано в уже упомянутой статье «Установка perl модулей». Далее, для автоматизации процесса сборки Slackware пакетов из perl модулей нам поможет замечательная утилита cpan2tgz. С её помощью можно по имени модуля собрать Slackware пакет, а также пакеты всех отсутствующих зависимых модулей. На сайте автора утилиты cpan2tgz выбираем пакет под вашу версию Slackware, скачиваем и устанавливаем его:

root@slack12:~# wget http://software.jaos.org/slackpacks/12.0/cpan2tgz-0.6.2-norch-1.tgz
...
root@slack12:~# installpkg cpan2tgz-0.6.2-noarch-1.tgz
Installing package cpan2tgz-0.6.2-noarch-1... 
PACKAGE DESCRIPTION:
cpan2tgz: cpan2tgz - create Slackware packages from CPAN Perl modules
cpan2tgz: 
cpan2tgz: Packaged by cpan2tgz
cpan2tgz: 
cpan2tgz: cpan2tgz by Jason Woodward 
cpan2tgz: 
cpan2tgz: http://software.jaos.org/
cpan2tgz: 
Executing install script for cpan2tgz-0.6.2-noarch-1...

Чтобы получить пакеты, например, runtime части web фремворка Catalyst можем воспользоватся командой:

root@slack12:~# cpan2tgz Catalyst

Начнется сборка пакетов, при этом большую часть времени работает утилита cpan, скачивая, распаковывая и устанавливая perl модули. После установки модуля cpan2tgz запаковывает его в tgz пакет с соблюдением стандартов. По умолчанию готовые пакеты помещаются в директорию /usr/src . В данном случае список состоит из:

perl-catalyst-runtime-5.7007-noarch-1.tgz
perl-cgi-simple-1.1-noarch-1.tgz
perl-class-accessor-0.31-noarch-1.tgz
perl-class-data-inheritable-0.06-noarch-1.tgz
perl-class-inspector-1.16-noarch-1.tgz
perl-compress-raw-zlib-2.005-i486-1.tgz
perl-compress-zlib-2.005-noarch-1.tgz
perl-data-dump-1.08-noarch-1.tgz
perl-file-modified-0.07-noarch-1.tgz
perl-html-parser-3.56-i486-1.tgz
perl-html-tagset-3.10-noarch-1.tgz
perl-http-body-0.9-noarch-1.tgz
perl-http-request-ascgi-0.5-noarch-1.tgz
perl-io-compress-base-2.005-noarch-1.tgz
perl-io-compress-zlib-2.005-noarch-1.tgz
perl-libwww-perl-5.806-noarch-1.tgz
perl-module-pluggable-3.6-noarch-1.tgz
perl-path-class-0.16-noarch-1.tgz
perl-sub-uplevel-0.14-noarch-1.tgz
perl-test-exception-0.25-noarch-1.tgz
perl-text-simpletable-0.03-noarch-1.tgz
perl-tree-simple-1.17-noarch-1.tgz
perl-tree-simple-visitorfactory-0.10-noarch-1.tgz
perl-version-0.7203-i486-1.tgz
perl-yaml-0.65-noarch-1.tgz

Теперь можно скопировать эти пакеты на рабочий сервер и установить c помощью команды:

root@slack12:~# installpkg *.tgz

Всё.