UMGUM.COM (лучше) 

MU Conference + Nginx + Perl ( Показ с помощью Nginx журнала MU Conference, оптимизированного Perl. )

22 февраля 2011  (обновлено 27 мая 2017)

OS: Debian GNU/Linux Lenny.

Задача: обеспечить возможность просмотра структурированных по дате создания журналов переписки в публичном "чате", работающем на движке "MU-Conference". Очень полезно для "разбора полётов" между службой технической поддержки и пользователями, в случае возникновения претензий или в самообразовательных целях.

Я знаю два способа сделать это:

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

Мне больше нравится второй путь, хотя бы и потому, что не нужно будет устанавливать лишнее программное обеспечение.

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

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


В пакете Nginx для Debian Lenny поддержка Perl не предусмотрена. Стало быть, нужно собрать свой пакет. Для создания рабочего окружения (скрипты инициализации, конфигурационные файлы, файлы журналов и тому подобного) я рекомендовал бы предварительно установить пакет Nginx, идущий с дистрибутивом Debian. Меньше возни с последующей настройкой:

# aptitude install nginx

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

# /etc/init.d/nginx start

Инсталлируем минимально необходимый набор пакетов Perl (если он уже не стоит в более расширенном варианте, разумеется):

# aptitude install perl-base libperl-dev

Устанавливаем утилиту, что соберет нам после сборки из исходных кодов пакет, готовый для установки в систему:

# aptitude install checkinstall

Инсталлятор потянет кроме указанных продуктов ещё как минимум build-essential, bzip, dpkg-dev, g++, make.

Устанавливаем пакеты, требующиеся свежему Nginx:

# aptitude install libpcre3 libpcre3-dev libssl-dev zlib1g-dev

Скачиваем дистрибутив по ссылке полученной с сайта разработчиков:

# cd /usr/src
# wget http://sysoev.ru/nginx/nginx-0.8.53.tar.gz

Распаковываем архив. Переходим в корень директории с исходными кодами:

# tar -xvf nginx-0.8.53.tar.gz
# cd ./nginx-0.8.53

Смотрим, не придумали ли разработчики чего нового, нет ли несовместимых с прежней конфигурацией ключей:

# ./configure --help

Проверяем, удовлетворяет ли наша система зависимостям устанавливаемого программного обеспечения:

# ./configure --prefix=/var/lib/nginx --sbin-path=/usr/sbin --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log \
  --user=www-data --group=www-data \
  --with-cc-opt="-I /usr/include" --with-ld-opt="-L /usr/lib" \
  --http-proxy-temp-path=/var/cache/nginx \
  --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_perl_module --with-http_ssl_module \
  --without-http_sub_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --without-http_geo_module --without-http_ssi_module --without-http_empty_gif_module --without-http_browser_module --without-http_memcached_module

Вывод конфигуратора "говорящий" и явно даёт понять, успешно ли прошла процедура.

Компилируем продукт:

# checkinstall -D --install=no --pkggroup=Nginx --pkgname=nginx-perl --pkgversion=0.8.53 --pkgrelease=1 --pkgsource=sysoev.ru --maintainer=your@mail.com make install

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

Done. The new package has been saved to

/usr/src/nginx-0.8.53/nginx-perl_0.8.53-1_i386.deb
You can install it in your system anytime using:

  dpkg -i nginx-perl_0.8.53-1_i386.deb

Останавливаем и удаляем пакет работающего ранее Nginx:

# /etc/init.d/nginx stop
# aptitude remove nginx

Устанавливаем подготовленный нами пакет Nginx+Perl:

# dpkg -i ./nginx-perl_0.8.53-1_i386.deb

Делаем резервные копии затрагиваемых нами конфигурационных файлов:

# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.dist

Перейдем к конфигурированию Nginx.

Общая конфигурация Nginx находится в файле "/etc/nginx/nginx.conf", конфигурации хостов и сайтов описываются в файлах, располагающихся в директориях "/etc/nginx/conf.d." и "/etc/nginx/sites-enabled.", подключаемых с помощью директив "include /etc/nginx/conf.d/*.conf;" и "include /etc/nginx/sites-enabled/*;".

Приведём общий конфигурационный файл "/etc/nginx/nginx.conf" к следующему виду:

# Указываем пользователя и группу, от чьего имени запускается Nginx
user www-data www-data;

# Количество запускаемых рабочих процессов приравняем к количеству процессорных ядер на нашем сервере
worker_processes    4;

# Указываем месторасположение журнального файла сообщений об ошибках
error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
  worker_connections  1024;
}

http {
  # Подключаем описание типов файлов
  include             /etc/nginx/mime.types;
  default_type        application/octet-stream;

  # Месторасположение журнального файла событий доступа
  access_log  /var/log/nginx/access.log;

  sendfile            on;
  keepalive_timeout   65;
  tcp_nodelay         on;

  # Запрещаем сообщать версию Nginx в ответе клиенту
  server_tokens       off;

  # Подключаем файлы описания дополнительных конфигураций
  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
}

Создаем файл конфигурации виртуального хоста "log.conference.xmpp.local":

# touch /etc/nginx/sites-available/log.conference.xmpp.local

Приводим его к следующему виду:

# Указываем на месторасположение самодельных модулей Perl
perl_modules  /var/lib/nginx/perl;
perl_require  cut-strings.pl;

server {
  listen      *:80;
  server_name log.conference.xmpp.local;

  # Указываем кодировку отдаваемых страниц
  charset     utf-8;

  # Указываем корень нашего web-ресурса
  root        /var/www/log.conference.xmpp.local;

  # Запрещаем отдавать кому бы то ни было файлы .htaccess и .htpasswd
  location ~* /\.ht {
    deny  all;
  }

  location / {
    # Размещаем вызов процедуры Perl в самом начале обработки обращения к ресурсу
    perl  cutter::handler;

    # Учим Nginx отображать содержимое директории и отдавать файлы
    autoindex on;
    autoindex_exact_size on;
    autoindex_localtime on;

    # Ограничиваем доступ к ресурсу
    allow 192.168.0.0/16;
    deny all;
  }
}

Создаём домик для скриптов Perl:

# mkdir -p /var/lib/nginx/perl
# touch /var/lib/nginx/perl/cut-strings.pl
# chown -R www-data:www-data /var/lib/nginx/perl

Пишем модуль с процедурой изменения "на лету" запрашиваемого ресурса:

# cat /var/lib/nginx/perl/cut-strings.pl

package cutter;
use nginx;

sub handler {
  my $resource = shift;

  # Отлавливаем ситуацию, когда запрошенный ресурс - текстовый файл
  if ( -T ($resource->filename) ) {

    # Инициируем сеанс передачи данных клиенту
    $resource->send_http_header;

    # Открываем для чтения запрашиваемый клиентом файл
    open(FLID, $resource->filename) || die "Error";

    # Перебираем последовательно все строки запрашиваемого файла
    while(<FLID>) {

      # Применяем к локальной переменной "$test" значение последней переменной "по умолчанию" "$_", используемой Perl при чтении данных из файла (какой-то хитрый способ Perl, суть которого мне не до конца ясна)
      my $test = $_;

      # Отлавливаем интересующие нас строк и выводим их в поток передачи клиенту
      if ($test =~ m/<span class=\"nick\">/i ) {
        $resource->print($test);
      }
    }

    # Закрываем сеанс работы с файлом
    close(FLID);

    # Завершаем соединение к клиентом
    return OK;

  } else {
    # ...иначе - передаём управление Nginx (для просмотра содержимого директории или выдачи затесавшегося не текстового файла)
      return DECLINED;
  }

}

1;

Указываем символической ссылкой Nginx на доступную конфигурацию виртуального хоста:

# ln -s /etc/nginx/sites-available/log.conference.xmpp.local /etc/nginx/sites-enabled/log.conference.xmpp.local

Перезапускаем Nginx:

# /etc/init.d/nginx restart

По завершению конфигурирования Nginx закрываем от постороннего взгляда директорию конфигурации:

# chown -R root:root /etc/nginx
# chmod -R o-rwx /etc/nginx


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


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )