вторник, 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

Всё.

четверг, 26 июля 2007 г.

Web анонсы

Провайдер сегодня порадовал. Принудительными анонсами. Открываешь страницу с произвольным адресом. Но самой этой страницы не видишь, а происходит перенаправление на внутренний сервер с рекламой. Выглядит это так:

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

Slackware 12

Наконец-то добрался до Slackware 12. Как обычно, сначала любую новую операционую систему я пробую устанавливать в виртуальной машине. Инсталяция прошла гладко, ни на шаг не отступая от классической схемы установки Slackware — консоль, разбиение диска с помощью fdisk, выбор пакетов для установки из списка. Как обычно выбираю абсолютный минимум необходимых пакетов. Отметил, что теперь по умолчанию предлагается форматировать разделы диска в ext3, вместо raiserfs как было раньше. Порадовало наличие пакета openvpn. До 12-ой версии Slackware похоже был последним дистрибутивом, содержащим веб сервер apache1. Теперь он заменен сразу на apache2.2!, кто-то наверное обрадуется, а мне немного грустно, т.к. возможностей apache1 мне хватало абсолютно.

Для каждой виртуальной машины я выделяю 48Мб памяти. Для Slackware с версий 9.1 по 11 этого вполне хватало не только для загрузки, но и для адекватной работы в качестве девелоперской машины LAMP сервером, естественно без иксов. Но вот загружается Slackware 12 и первое впечатление — дааа, потяжелела слакварь, курсор в консоле еле ворочается, память занята вся и ещё немало подкачки отъела.

Однако проблема довольно быстро решается:

  1. Отключаем появившиеся в Слаке новомодные сервисы, необходимые только для десктопа. Для этого снимаем атрибут исполняемого файла с:

    • /etc/rc.d/rc.hald
    • /etc/rc.d/rc.messagebus
    • /etc/rc.d/rc.udev
  2. В /etc/rc.d/rc.modules отключаем загрузку ненужных модулей ядра, а именно:

    # /sbin/modprobe psmouse proto=imps
    # /sbin/modprobe pcspkr
    # /sbin/modprobe -q parport_pc 2> /dev/null
    # /sbin/modprobe agpgart 2> /dev/null
    # /sbin/modprobe capability

    После этого в памяти оставался ещё не нужный нам модуль ядра ipv6. Его отключаем добавлением следующих строчек в /etc/modprobe.d/blacklist:

    alias net-pf-10 off
    blacklist ipv6
  3. Многие знают, что Slackware 12, тоже одним из последних, перешел на ядро 2.6. Но не все знают, что теперь в Slackware 12 есть две сборки ядра, называемые huge и generic. По умолчанию грузится huge, где большинство модулей вкомпилены в ядро. Так не возникают проблемы при загрузкой с разных файловых систем, но это ядро занимает много памяти. Чтобы переключится на generic ядро скорее вам всего нужно будет собрать initrd, содержащий как минимум модуль ядра для корневой файловой системы. Краткие объяснения и инструкция содержатся в файле /boot/README.initrd. В моём случае понадобилось выполнить следующую команду:

    mkinitrd -c -k 2.6.21.5-smp -m ext3

    Добавляем пункт загрузки с generic ядра в меню lilo, для этого вставляем строки в файл /etc/lilo.conf:

    image = /boot/vmlinuz-generic-smp-2.6.21.5-smp
      initrd = /boot/initrd.gz
      root = /dev/XXXN
      label = Linux-generic
      read-only

После этих действий система стала вести себя более отзывчиво :-). 48 Мб опять хватает. В общем я доволен. Мы получили дистрибутив, который с одной стороны идет в ногу со временем, включающий последние достижения Open Source, обновленные версии всех программ. С другой стороны Slackware строго придерживается собственных традиций, устанавливаются оригинальные версии программ, без патчей. Позволяется максимально возможную гибкость в настройке системы. В общем, я всё больше убеждаюсь, что Slacware лучшая ОС для серверных решений.

понедельник, 16 июля 2007 г.

Фильтрация спама для Qmail c помощью SpamAssassin

Все написанное производилось для Slackware 9.1. Описание установки и настройки Qmail, а также описание установки SpamAssassin не приводится. Почта пользователей сервера myserver.ru хранится в домашних каталогах пользователей в Maildir формате.

Спам — достал. Способов борьбы с ним тьма, но что-то же выбрать надо. Что мне понравилось в SpamAssassin, это отсутствие необходимости постоянно в ручную обучать его новому спаму, чтобы он работал эффективно. То есть, при желании это можно делать, но пользователей обучить нереально, а сисадмину и так есть чем занятся :-).

Для работы SpamAssassin использует огромную базу правил. Каждому правилу назначается определенный вес. При проверке письма веса всех «сработавших» правил суммируются. Если сумма превысила пороговое значение, письмо помечается как спам. База всех правил постоянно пополняется, весовые коэффициенты уточняются. SpamAssassin предоставляет утилиту для обновления базы правил, которую можно запускать в автоматическом режиме по расписанию.

Есть два способа обращаться к SpamAssasin:

  1. в режиме утилиты командной строки — spamassasin,
  2. в режиме клиента spamc для демона spamd.

Второй вариант работает быстрее, т.к. не тратится время на запуск и инициализацию программы. Однако расходует больше памяти, т.к. демон должен быть постоянно запущен. Как показала практика, SpamAssassin достаточно тяжел в работе, на принятие решения по одному письму уходит от 2-х до 7 секунд работы программы. А памяти на серверах обычно много и она дешева. Поэтому используем второй вариант. Для автоматического запуска демона spamd при загрузке сервера прописываем в файле /etc/rc.d/rc.M строчки:

# Start the SpamAssasin daemon:
if [ -x /etc/rc.d/rc.spamd ]; then
  /etc/rc.d/rc.spamd start
fi

Вики SpamAssasin предлагает три способа интеграции с qmail:

  1. Через программу Simscan глобально на этапе приема письма по smtp;
  2. Через программу qmail-scanner глобально на этапе пересылки/доставки письма;
  3. Через скрипт ifspamh и редактирование файла ~/.qmail для индивидуального почтового ящика на этапе локальной доставки письма;

Используем третий способ, как самый безопасный для экспериментов на работающем сервере. Устанавливаем скрипт ifspamh:

cd /usr/local/bin
wget http://www.gbnet.net/~jrg/qmail/ifspamh/ifspamh
chmod +x ifspamh

Скрипт ifspamh «из коробки» не заработал, пришлось немного подпилить. Вместо оболочки ksh, которую я не устанавливал прописал запуск из bash. На работоспособность скрипта это не повлияло. Подправил пути поиска утилит spamc, forward (входит в qmail) и 822field. Утилита 822field входит в состав пакета mess822. Мне повезло, пакет mess822 для Slackware 9.1 был на linuxpackages.net. А если бы не было, так не беда — сам бы собрал, просто ленив я стал...

Для каждого пользователя, которому нужна фильтрация спама редактируем файл ~/.qmail:

|/usr/local/bin/ifspamh spam@myserver.ru
./Maildir/

Теперь весь обнаруженный спам будет пересылаться на ящик spam@myserver.ru, эдакий спамоотстойник сервера. Доставки в локальный ящик не будет. Письма не удаляются, администратор всегда сможет найти ложно отфильтрованное письмо в отстойнике. Теперь проверим работу обновления базы правил SpamAssassin, для этого используется утилита sa-update. Запустим её без параметров, если все пройдёт успешно, то в каталоге /var/lib/spamassassin/<version>/ появятся обновленные базы правил. Чтобы обновления вступили в силу, демон spamd необходимо перезапустить. Прописать запуск sa-update в автоматическом режиме по расписанию я пока не решился. Но тем не менее crontab изменить пришлось:

# 0 2 * * * sa-update && /etc/rc.d/rc.spamd restart
0 3 * * * find ~spam/Maildir -ctime +31 -type f -exec rm {} \;

Как вы заметили, я добавил очистку ящика spam@myserver.ru, чтобы этот отстойник не переполнился. Если письмо в течении месяца никому так и не понадобилось, то его можно спокойно удалить.

За прошедший (не очень продолжительный) период работы не было ни одного ложного срабатывания. Эффективность обнаружения спама около 97%. Всё.

пятница, 13 июля 2007 г.

Про ФСБ

Повествовательный рассказ без выводов и нравоучений про ФСБ.

Однажды, в начале лета 2006 года, мне позвонил весьма отдаленный знакомый:

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

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

Дня через два позвонил, назовем его пока Джеймс Бонд, предложил встретится в кафешке. Так и сделали. Бонд оказался молодым человеком, не отталкивающей наружности. Далее так написали бы в шпионском романе: «Бонд выбрал столик с хорошим обзором всего кафе и входной двери. При этом любой входящий в зал, оказывался повернут в пол оборота, так что его можно было хорошо рассмотреть, оставаясь самому незамеченным. Бонд предложил мне сесть к стене, так что я фактически оказался заперт за столом, не имея возможности встать и уйти, пока он сам меня не выпустит». Заказали мы, к сожалению, не по бокалу любимого напитка киногероя — мартини, а по пиву и Бонд начал разговор:

— Ты наверное в детстве много читал?

Я ответил утвердительно.

— Наверное читал «Щит и меч»?

Я удивился, но чтобы не грешить против истины, опять ответил утвердительно. После аналогичного вопроса про «Семнадцать мгновений весны» начался пространный рассказ о том, что отечество в опасности, НАТО не дремлет, загнивающие буржуи окружают. Например, недавно поймали китайцев, фотографирующих расположение наших военных частей. Или с авиационного завода пытались продать какую-то документацию. Я решаю прервать этот поток сознания:

— А ты собственно кто?

Не говоря ни слова Бонд достает корочку удостоверения и предъявляет её мне. Разоблачается таким образом в лейтенанта ФСБ Антона Митина. Я начинаю себя чувствовать неуютно. Тем временем, пространный рассказ продолжается. Оказывается, с его слов, Митин — главный специалист ФСБ по информационной безопасности в городе. Все остальные уже в возрасте, он единственный кто соображает. Информационные преступления на каждом шагу, а его «служба и опасна и трудна», он не успевает в одиночку с ними справляться. Рисуется образ печального рыцаря, преданного делу короны. Снова мне приходится прервать его:

— Хорошо, а что ты хочешь от меня?

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

— Это тянет на статью «получение незаконного доступа к программам или базам данных» и/или «незаконная модификацию программ или баз данных». До 2-х лет, если не ошибаюсь, в формулировках и сроках ты лучше разбираешься.

— Вот ты повернул! Мне такое даже и в голову бы не пришло, тем более что привлечь по этой статье нереально. Хорошо давай мы сами её найдем, тебе только взломать останется. Ты же, например, Windows взломанным пользуешься?

— У меня на рабочем и на домашнем компьютере нет ни Windows, ни одной другой краденной программы.

Митин-Бонд посмотрел на меня с недоверием, но ничего не возразил. Начал расспрашивать меня о моей работе. Когда разговор, коснулся Open Source глаза его вспыхнули и он произнес: «Да это же транснациональные организованные сообщества!». Кроме того хвалился, что поддерживает постоянную связь с начальником безопасности моей конторы, бывшим КГБистом, и уже «пробил» всё про меня. Потом произнес:

— У нас не хватает сведений об информационных преступления. Я же один на весь город. Мог бы ты, если где-то что-то краем уха услышишь, сообщать мне? Или вдруг в англоязычных рассылках чего промелькнёт. Например, вдруг кто-нибудь из участников работает в Боинге, а Боинг ведь на наш авиазавод моторы поставлять будет...

Тут я почувствовал себя гадко, по-настоящему гадко, как будто в говно случайно наступил. То что меня будут вербовать в качестве стукача, я никак не ожидал:

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

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

— Нет. На этом я хотел бы завершить наш разговор.

— Пожалуйста.

На этом мы распрощались. Митин взял с меня обещание никому не распространяться об этом разговоре. Больше, слава богу, я его не видел, и надеюсь никогда не увижу.

пятница, 6 июля 2007 г.

Генерация Excel документов на perl

Описание задачи. Имеется программная телефонная станция на базе asterisk. Журнал звонков этой телефонной станции ведется в базе данных mysql. Названия полей таблицы соответствуют названиям полей CDR (Call Detail Record). Возникла необходимость в доступе к этому журналу для менеджеров. Менеджеры, братья наши меньшие, абсолютно не очарованы таблицами баз данных, SQL для них чужд. Зато документы в формате Excel милы их сердцам. Поэтому напишем perl скрипт для генерации Excel отчета из базы данных. Для создания excel файлов воспользуемся perl модулем Excel::Template, позволяющем, как видно из названия, создавать .xls файлы на основе xml шаблона. Вы ведь не хотите менять программу каждый раз, когда нужно будет увеличить размер шрифта или поменять местами колонки в отчете? Сначала приведем содержимое файла шаблона report.xml:
<workbook>
 <worksheet name="report">
   <format align="center" valign="vcenter" bold="bold" border="2">
     <row>
       <cell width="15">Откуда</cell>
       <cell width="15">Куда</cell>
       <cell width="15">Начало</cell>
       <cell width="15">Длительность</cell>
     </row>
   </format>

   <format border="1">
     <loop name="report_data">
       <row>
         <cell><var name="src" /></cell>
         <cell><var name="dst" /></cell>
         <cell><var name="start" /></cell>
         <cell><var name="billsec" /></cell>
       </row>
     </loop>
   </format>
 </worksheet>
</workbook>
В данном шаблоне описывается excel документ, содержащий один лист с данными. На этом листе первая строка содержит заголовки 4-х колонок отчета: «Откуда» — номер вызывающего абонента, «Куда» — номер вызываемого абонента, «Начало» — время начала звонка, «Длительность» — длительность звонка. Остальные строки заполняются данными отчета по количеству записей в нём. Подробное описание всех тегов шаблона присутствует в документации perl модуля Excel::Template. Теперь сам скрипт report.pl:
#!/usr/bin/perl -w -t
use strict;

use DateTime;
use DBI;
use Excel::Template;

# подключение к базе данных
my $dsn    = 'dbi:mysql:database=...;host=...';
my $dbuser = '...';
my $dbpass = '...';
my $dbh    = DBI->connect( $dsn, $dbuser, $dbpass, { RaiseError => 1 } );

# задаем период формирования отчета
my $period_begin = DateTime->new( year => 2007, month => 6, day => 1 );
my $period_end   = DateTime->new( year => 2007, month => 7, day => 1 );

# подготовка и исполнение sql запроса на выборку данных
my $sth = $dbh->prepare( q/
    SELECT `src`, `dst`, `start`, `answer`, `end`, `duration`
    FROM   `cdr`
    WHERE  `start` BETWEEN ? AND ?
/ );
$sth->execute( $period_begin, $period_end );

# извлечение данных из базы и подготовка их для шаблона
my @report_data;
while ( my $report_row = $sth->fetchrow_hashref ) {
    push @report_data, $report_row;
}

# формирование excel отчета по шаблону и данным
my $template_file = 'report.xml';
my $template = Excel::Template->new( filename => $template_file );
$template->param( report_data => \@report_data );
print $template->output;

Скрипт report.pl выдает excel отчет на стандартный поток вывода, поэтому вызывать его нужно так: « ./report.pl > report.xls ». Как видите — ничего сложного. Подобным же образом можно генерировать excel документы и для web.

P.S. Данный скрипт работоспособный, хотя и был немного упрощен, чтобы донести основную идею использования шаблонов. На самом деле условия отбора записей сложнее, период формирования отчета задается в аргументах скрипта report.pl; даты преобразуются во внутренний формат excel, а не вставлются текстовой строкой; решены вопросы c кодировками. Но опытному perl программисту не составит труда адаптировать этот скрипт под свои нужды.

среда, 4 июля 2007 г.

Установка perl модулей

CPAN - это средоточие интеллектуальной мощи десятков известных и (и сотен не очень известных) perl-хакеров. Это сетевой архив тысяч perl модулей, охватывающий абсолютно все мыслимые области применения программирования. Определенно, perl сегодня не занимал бы того место, которое он занимает сейчас, если бы не было CPAN, отметившего в 2005 году своё десятилетие. Правилом любого perl программиста должно быть: сначала ищи на CPAN и только потом, в случае отсутствия там, уже пиши сам. Ведь работодатель вас ценит и платит за то, что вы умеете быстро собирать работающие машины (программы) из готовых запчастей (perl модули из CPAN), а не тратите недели рабочего времени на изобретение заново колес и шестеренок (библиотеки классов и функций). Perl модули распространяются в виде архивов исходного кода с расширением .tar.gz. В одном архиве исходного кода может быть несколько perl модулей. Основной веб-интерфейс для работы с CPAN — http://search.cpan.org. На этом сайте можно найти интересующий perl модуль по структурированному каталогу или по имени. Для каждого модуля можно прочитать встроенную документацию и исходный код. Как правило, все perl модули очень хорошо документированы. Естественно, можно скачать архив исходного кода. В каждом архиве исходного кода прилагается инструкция по установке, обычно она включает распаковку архива и выполнение команд:
perl Makefile.PL
make
make test
make install
Такой метод установки прекрасно работает, но им неудобно пользоваться. Почему? Из-за зависимостей модулей. Например, для установки часто используемой библиотеки модулей LWP (libwebperl — библиотека для работы с web из perl) требуются уже установленные perl модули: URI, Compress::Zlib, HTML::Parser. В свою очередь, для установки модуля Compress::Zlib требуются уже установленные модули: IO::Uncompress::Gunzip, IO::Compress::Gzip, Compress::Raw::Zlib, IO::Uncompress::Base, IO::Compress::Gzip::Constants, IO::Compress::Base и IO::Compress::Base::Common. И так далее... дерево зависимостей может быть очень большим. Скачивать и устанавливать все модули в ручную — просто потеря времени. Для автоматизации процесса разрешения зависимостей существует специальный perl модуль CPAN. В его состав входит утилита cpan, предоставляющая консоль доступа к архиву. Ею мы и будем пользоваться. При первом запуске утилиты будет задано несколько вопросов по параметрам конфигурации. Ответы по умолчанию выбраны достаточно разумно, поэтому я не вижу смысла отказываться от автоматического конфигурирования:
root@slack11:~# cpan
/usr/lib/perl5/5.8.8/CPAN/Config.pm initialized.
...
Are you ready for manual configuration? [yes] no
...
cpan shell -- CPAN exploration and modules installation (v1.7602)
cpan>
Если для доступа в интернет используется http proxy сервер, то необходимо задать параметры ftp_proxy и http_proxy. Если proxy сервер требует авторизацию, то url задается по схеме "http://login:password@adrr:port/":
cpan> o conf ftp_proxy "http://adrr:port/"
    ftp_proxy          http://adrr:port/
cpan> o conf http_proxy "http://adrr:port/"
    http_proxy         http://adrr:port/
cpan> o conf commit
Чтобы проверить связь cpan с внешним миром, можно загрузить информацию о текущем состоянии базы данных модулей:
cpan> reload index
Теперь модуль CPAN сконфигурирован и готов к работе. Например, можно установить уже упоминавшуюся библиотеку LWP со всеми зависимостями с помощью команды:
cpan> install LWP
Остается только смотреть на мелькающие надписи, чувствуя себя в матрице. Однако полностью расслабится не удастся, изредка придется отвечать на возникающие на экране на вопросы. Вот собственно и всё, теперь установить любой perl модуль — дело нескольких минут. В завершение хочется отметить, что алгоритм разрешения зависимостей модулей постоянно совершенствуется, changelog впечатляет. Поэтому можно порекомендовать обновить саму утилиту cpan и установить дополнительные модули, облегчающие её работу. Утилита cpan может обновить сама себя, для этого следует выполнить команду:
cpan> install Bundle::CPAN
После обновления утилиты cpan, её надо перезапустить, чтобы изменения вступили в силу. Скорее всего придется заново пройти этап конфигурирования, в автоматическом режиме, конечно :-). Вы сразу заметите, что в консоле cpan появилась возможность пролистать историю ранее введенных команд.

пятница, 29 июня 2007 г.

Оптимизация загрузки Slackware

Сразу обозначу с какой целью производится оптимизация. В конторе, где я работаю, Slackware Linux используется на большинстве серверов. Для тестирования решений, разработки новых программ, сборки slackware пакетов я также использую Slackware, но только внутри виртуальной машины. Соответственно вся оптимизация применяется для виртуальной машины. Особенности работы:
  • не используется графический режим, устанавливаются и работают только консольные программы. Фреймбуфер тоже не используется.
  • доступ только через ssh, как потом на рабочем сервере.
Всё сказанное здесь верно для всех известных версий Slackware, статья тестировалась на Slackware 11. Можно использовать описанные здесь приёмы и для рабочих машин, но делать это с осторожностью.
  1. Настройка загрузчика lilo. Произвоится редактированием файла /etc/lilo.conf. Задаем параметры:
    # графический режим консоли - текстовый
    vga = normal
    # задержка перед автоматической загрузкой - 5 секунд
    timeout = 50
    
    Если не планируется пересобирать ядро или менять параметры его загрузки, можно вообще отключить вывод меню:
    # prompt
    
    После изменения /etc/lilo.conf, не забудьте запустить lilo, чтобы изменение настроек вступило в силу.
  2. Отключение лишних консолей. Редактируем файл /etc/inittab. Оставим одну из шести консолей, остальные комментируем:
    c1:1235:respawn:/sbin/agetty 38400 tty1 linux
    # c2:1235:respawn:/sbin/agetty 38400 tty2 linux
    # c3:1235:respawn:/sbin/agetty 38400 tty3 linux
    # c4:1235:respawn:/sbin/agetty 38400 tty4 linux
    # c5:1235:respawn:/sbin/agetty 38400 tty5 linux
    # c6:12345:respawn:/sbin/agetty 38400 tty6 linux
    
  3. Отключение загрузки неиспользуемых модулей ядра. Смотрим файл /etc/rc.d/rc.modules. Здесь можно отключить загрузку модулей agp и эмуляции scsi:
    # /sbin/modprobe agpgart
    ...
    # /sbin/modprobe ide-scsi
    
  4. Отключение неиспользуемых демонов. С помощью комманды: chmod -x /etc/rc.d/rc.xxxxx снимаем атрибут исполняемого файла, со всех файлов в каталоге /etc/rc.d, кроме:
    /etc/rc.d/rc.4
    /etc/rc.d/rc.6
    /etc/rc.d/rc.K
    /etc/rc.d/rc.M
    /etc/rc.d/rc.S
    /etc/rc.d/rc.inet1
    /etc/rc.d/rc.inet2
    /etc/rc.d/rc.modules-2.4.33.3
    /etc/rc.d/rc.netdevice
    /etc/rc.d/rc.sshd
    /etc/rc.d/rc.syslog
    
  5. Отключение неиспользуемых демонов 2. Чтобы отключить демон отсроченного запуска комманд и обновление индекса шрифтов, комментируем следующие строчки в файле /etc/rc.d/rc.M :
    # Start atd (manages jobs scheduled with 'at'):
    # if [ -x /usr/sbin/atd ]; then
    #   /usr/sbin/atd -b 15 -l 1
    # fi
    ...
    # Update the X font indexes:
    # if [ -x /usr/X11R6/bin/fc-cache ]; then
    #   echo "Updating X font indexes:  /usr/X11R6/bin/fc-cache"
    #   /usr/X11R6/bin/fc-cache
    # fi
    
  6. Отключение демонов 3. Для экстремалов. Можно (но не рекомендуется) отключить демона журналирования syslog:
    chmod -x /etc/rc.d/rc.syslog
    
    Тогда отпадает надобность в демоне запуска заданий по расписанию, используемом для ротации журналов. Комментируем строчки в файле /etc/rc.d/rc.M :
    # Start crond (Dillon's crond):
    # If you want cron to actually log activity to /var/log/cron, then change
    # -l10 to -l8 to increase the logging level.
    # if [ -x /usr/sbin/crond ]; then
    #   /usr/sbin/crond -l10 >>/var/log/cron 2>&1
    # fi
    
Теперь остается перезагрузить виртуальную машину и убедится что всё работает. Самое время сделать снимок состояния виртуальной машины для многократного использования в будущем.