Шукати в цьому блозі

Показ дописів із міткою perl. Показати всі дописи
Показ дописів із міткою perl. Показати всі дописи

четвер, 27 жовтня 2016 р.

RouterOS та передача маршрутної інформації у DHCP

Певно, що тим, хто читає цей нотаток, відомо, що у DHCP можна передавати окрім всього іншого й маршрутну інформацію. Тут розглянемо як це робиться у RouterOS та намалюємо маленький скрипт який допоможе в цій роботі у подальшому.

RFC3442 має назву The Classless Static Route Option for Dynamic Host Configuration Protocol (DHCP) version 4 і описує формат опції 121, в якій передається маршрутна інформація. Для тієї самої задачі слугує й опція 249, але про неї окремо.

Формат опції у RFC виглядає так:
  Code Len Destination 1    Router 1
   +-----+---+----+-----+----+----+----+----+----+
   | 121 | n | d1 | ... | dN | r1 | r2 | r3 | r4 |
   +-----+---+----+-----+----+----+----+----+----+

    Destination 2       Router 2
   +----+-----+----+----+----+----+----+
   | d1 | ... | dN | r1 | r2 | r3 | r4 |
   +----+-----+----+----+----+----+----+
Тобто маємо безпосередньо код опції, наступний байт це кількість мережевих бітів (маска мережі), потім йдуть октети, що описують номер мережі та 4 байти/октети, що описують маршрутизатор через який має бути побудовано маршрут. Також у RFC читаємо, що для декількох маршрутів вони можуть бути склеєні.

Окрему увагу заслуговує кількість Destination октетів. У RFC можна побачити наступне:
        Width of subnet mask     Number of significant octets
                     0                     0
                  1- 8                     1
                  9-16                     2
                 17-24                     3
                 25-32                     4
Це все справедливо як для опції 121 так і для опції 249. Єдине зауваження щодо опції 249, яке знайшов на хабрі, те, що до маршрутної інформації варто додавати 00[адреса шлюзу]. Пишуть, що це справедливо для комп'ютерів під керуванням ОС Windows.

Все це була не дуже цікава, але не менш важлива теорія, приступимо до практики.

Озброївшись знаннями з RFC3442 можна доволі швидко написати додаток, що буде обчислювати маршрути й формувати відповідний вивід. Я полюбляю Perl тому скрипт було написано саме на ньому, https://github.com/oldengremlin/route-4-dhcp/blob/master/rfc3442.route-4-dhcp.pl:

Поставимо на меті описати маршрут на мережі RFC1918 через /dev/null. Взагалі то було б непогано змаршрутизувати їх через 127.0.0.1, але ж через описані опції маршрути можуть бути додано лише через ті адреси до яких клієнт може знати як дістатися. Тому, припустимо, що у нашій мережі 192.168.88.0/24 не існує хоста 192.168.88.2, а трафік пустимо через нього.

Назвемо скрипт rfc3442.route-4-dhcp та запустимо його з параметрами:
$ rfc3442.route-4-dhcp 10.0.0.0/8 192.168.88.2 172.16.0.0/12 192.168.88.2 192.168.0.0/16 192.168.88.2
option_121_route_10.0.0.0/8_via_192.168.88.2 : 0x080ac0a85802
option_249_route_10.0.0.0/8_via_192.168.88.2 : 0x080ac0a85802
option_121_route_172.16.0.0/12_via_192.168.88.2 : 0x0cac10c0a85802
option_249_route_172.16.0.0/12_via_192.168.88.2 : 0x0cac10c0a85802
option_121_route_192.168.0.0/16_via_192.168.88.2 : 0x10c0a8c0a85802
option_249_route_192.168.0.0/16_via_192.168.88.2 : 0x10c0a8c0a85802
aggregate_opt_121 : 0x080ac0a858020cac10c0a8580210c0a8c0a85802
aggregate_opt_249 : 0x080ac0a858020cac10c0a8580210c0a8c0a85802

Передаємо скрипту пари у вигляді мережа-шлюз і отримуємо попарний вивід для окремих мереж і останніми строками сукупну маршрутну інформацію для всіх мереж.

Тепер перенесемо всю цю інформацію у RouterOS:
/ip dhcp-server option
add code=121 name=aggregate_opt_121_over_fakeip_192.168.88.2 value=0x080ac0a858020cac10c0a8580210c0a8c0a85802
add code=249 name=aggregate_opt_249_over_fakeip_192.168.88.2 value=0x080ac0a858020cac10c0a8580210c0a8c0a8580200c0a85801

Щодо опції 249 читаємо зауваження нагорі і дивимося як було додано маршрут через основну адресу маршрутизатора - 192.168.88.1.

Опції задано, тепер їх можна додати у список опцій у описі мережі в налаштуваннях dhcp-серверу. Якщо у dhcp-сервері вже було налаштовано передачу інформації щодо wpad то разом з маршрутною інформацією команда налаштування мережі може виглядати якось так:
/ip dhcp-server network
add address=192.168.88.0/24 comment=dhcp-server dhcp-option=\
    auto-proxy-config,aggregate_opt_121_over_fakeip_192.168.88.2,aggregate_opt_249_over_fakeip_192.168.88.2,disable_nbt dns-server=\
    192.168.88.1 gateway=192.168.88.1 netmask=24 ntp-server=192.168.88.1

Домашнім завданням може бути написання скрипту якій розшифровує 0x080ac0a858020cac10c0a8580210c0a8c0a85802 у зворотньому напрямку ;)

понеділок, 7 березня 2016 р.

Тестування SMTP та ESMTP через telnet

SMTP (Simple Mail Transfer Protocol, Простий Протокол Пересилання Пошти) - це протокол, який використовується для пересилання електронної пошти до поштового сервера або з клієнта-комп'ютера, або між поштовими серверами. В IANA для SMTP зареєстрований порт 25. SMTP з'єднання де застосовується SSL шифрування використовують порт 465. Формально SMTP визначений в RFC 821 (STD 10) та покращений RFC 1123 (STD 3) розділ 5. Протокол, який використовується зараз, також відомий як ESMTP і визначений в RFC 2821.

Окрім з'єднань між MTA (Mail Transfer Agent), зі сторони клієнта з'єднатися з smtp-сервером можна як за допомогою налаштованого MUA (Mail User Agent) так і за допомогою telnet на 25/tcp порт. Щоб швидко перевірити чи smtp-сервер взагалі слухає та хоч якось працює останнього цілком достатньо.

Перевіряємо SMTP.
telnet сервер 25
Після того як з'єднання з smtp-сервером буде встановлено і отримаємо привітання, щось на кшталт
220 smtp.server.com, ESMTP
Можна спробувати ввести одна за одною наступні smtp-команди:
HELO localhost
MAIL FROM: <sender@server.com>
RCPT TO: <user1@server.com>
RCPT TO: <user2@server.com>
DATA
From: Sender <sender@server.com>
To: Receiver1 <user1@server.com>
To: Receiver2 <user2@server.com>
Subject: Test SMTP
Content-Type: text/plain

Hi!
Test SMTP.

.
QUIT
Варто зауважити, що якщо ви не є визнаним користувачем smtp-сервера (наприклад, абонентом провайдера до smtp-сервера якого хочете отримати доступ) то smtp-сервер може або не прийняти з'єднання або ж на будь-якому етапі перервати його, якщо таку дію налаштовано задля забезпечення унеможливлювання пересилання спаму.

Іноді, але не завжди, smtp-сервера для своїх користувачів надають можливість надсилати пошту з будь-якої частини Мережі, за умови позитивного проходження аутентифікації. Аутентифікація є розширенням до протоколу SMTP. Для її перевірки попередньо знадобиться виконати дві команди: перша ідентифікую користувача сервера, друга його пароль:
~$ perl -MMIME::Base64 -e 'print encode_base64("sender\@server.com");'
c2VuZGVyQHNlcnZlci5jb20=
~$ perl -MMIME::Base64 -e 'print encode_base64("pa\$\$w0rd");'
cGEkJHcwcmQ=

Після цього можна спробувати поспілкуватися з smtp-сервером і спробувати авторизуватися:
EHLO localhost
AUTH LOGIN
c2VuZGVyQHNlcnZlci5jb20=
cGEkJHcwcmQ=
MAIL FROM: <sender@server.com>
RCPT TO: <user1@server.com>
RCPT TO: <user2@server.com>
DATA
From: Sender <sender@server.com>
To: Receiver1 <user1@server.com>
To: Receiver2 <user2@server.com>
Subject: Test SMTP
Content-Type: text/plain

Hi!
Test Auth.

.
QUIT

Замість AUTH LOGIN до речі можна використовувати й AUTH PLAIN чи, наприклад, AUTH CRAM-MD5, якщо це підтримується сервером і якщо знаєте як цим користуватися.

Варто також зауважити, що у наведених прикладах localhost варто замінити на реальне ім'я своєї системи, а у полях from та to вказувати реальних користувачів, інакше сервер легко може сприйняти вас за спамера і, відповідно, заблокувати відправлення пошти.

середа, 20 серпня 2014 р.

Perl feature

feature (особенность) - Perl прагма для включения нового функционала. Детальное описание feature можно найти в perldoc, а тут приведу лишь некий краткий анонс.

В общем случае feature в perl-коде включаются следующим образом:
 use feature qw(say switch);
given ($foo) {
    when (1)          { say "\$foo == 1" }
    when ([2,3])      { say "\$foo == 2 || \$foo == 3" }
    when (/^a[bc]d$/) { say "\$foo eq 'abd' || \$foo eq 'acd'" }
    when ($_ > 100)   { say "\$foo > 100" }
    default           { say "None of the above" }
}
use feature ':5.10'; # загружает все feature доступные в perl 5.10
use v5.10;           # неявно загружает :5.10 feature
Как правило невозможно добавит в perl-скрипт новый синтаксис, не нарушая существующий код. Использование feature даёт возможность минимизировать этот риск. Новые синтаксические конструкции могут быть включены лишь в часть кода и будут разбираться лишь тогда когда соответствующая прагма находится в области видимости. Тем не менее использование префикса CORE::префикса позволяет использовать все новые ключевые слова Perl, независимо от использование директивы feature. Например:
use feature "say";
say "test0";
или
CORE::say "test0";

no feature - отключает действие feature:
use feature 'say';
say "say is available here";
{
    no feature 'say';
    print "But not here.\n";
}
say "Yet it is here.";

use feature 'say' - включает использование Perl6 функции say.
Функция say аналогична print, но к выводу добавляет "\n".
Эта feature доступна с версии Perl 5.10.

use feature 'state' - сообщает компилятору о включении переменных состояния (state).
Для детального ознакомления изучаем Persistent Private Variables.
Эта feature доступна с версии Perl 5.10.
use feature 'state';
sub gimme_another { state $x; return ++$x }
Пример с использованием анонимной функции:
use feature 'state';
sub create_counter {
    return sub { state $x; return ++$x }
}

use feature 'unicode_strings' - сообщает компилятору использовать правила Unicode во всех строковых операциях, попадающих в сферу его действия feature. Это же относится и к регулярным выражениям. При этом внутреннее представление не изменяется, меняется лишь их интерпретация.
Рекомендуется изучить Perl Unicode Bug во избежание сюрпризов и недоразумений.
Эта функция доступна начиная с Perl 5.12; была почти полностью реализована в Perl 5.14; и продлена в Perl 5.16, чтобы перекрыть quotemeta.

use feature 'fc' - говорит компилятору включить поддержку функции fc.
fc EXPR - возвращает регистронезависимую версию EXPR.
lc($this) eq lc($that)    # Wrong!
    # или
uc($this) eq uc($that)    # Also wrong!
    # или
$this =~ /^\Q$that\E\z/i  # Right!
Теперь можно писать так
fc($this) eq fc($that)

Комплектное включение feature
  Комплект  Включенные особенности
  --------- -----------------
  :default  array_base
  :5.10     say state switch array_base
  :5.12     say state switch unicode_strings array_base
  :5.14     say state switch unicode_strings array_base
  :5.16     say state switch unicode_strings
            unicode_eval evalbytes current_sub fc
  :5.18     say state switch unicode_strings
            unicode_eval evalbytes current_sub fc
  :5.20     say state switch unicode_strings
            unicode_eval evalbytes current_sub fc
Включение подверсии в feature не оказывает никакого эффекта. Например
use feature ":5.14.0";    # тоже, что и ":5.14"
use feature ":5.14.1";    # тоже, что и ":5.14"

Неявная загрузка feature.
Вместо загрузки отдельных feature можно позволить Perl неявно загрузить всё самому.
Для "однострочников" можно вместо -e использовать -E.
В скриптах - указать минимально используемую версию Perl. То есть:
use v5.10.0;
неявно сделает:
no feature ':all';
use feature ':5.10';

вівторок, 19 листопада 2013 р.

AnyEvent::SNMP

Понадобилось опросить по SNMP одно устройство, но так как в своё время разбирался с механизмом AnyEvent в perl то захотелось и в этом случае его использовать. К счастью модуль AnyEvent::SNMP в связке с Net::SNMP даёт такую возможность.
Собственно вот небольшой пример как эту связку использовать:
use AnyEvent::SNMP;
use Net::SNMP;

...

sub snmp {
    my @hosts = ('host10', 'host11');
    my @oids = (
        '.1.3.6.1.4.1.476.1.42.3.4.1.3.3.1.3.1',        # EnvTemperatureMeasurementDegC
        '.1.3.6.1.4.1.476.1.42.3.4.3.1.0'               # EnvStateSystem
    );
    my $community = "community";

    foreach my $host (@hosts) {

        printf("HOST: %s", $host);

        my $cv = AnyEvent->condvar;

        # Set timer 50 sec.
        my $w = AnyEvent->timer (after => 50, cb => sub { $cv->send("Timeout"); });

        Net::SNMP->session( -hostname => $host, -community => $community, -version => 'snmpv2c', -nonblocking => 1 )->get_request(
            -callback => sub {
                my $snmpSess = shift;
                my %oidsret;
                if ( defined $snmpSess->var_bind_list() ) {
                    foreach my $oid (@oids) { $oidsret{$oid} = $snmpSess->var_bind_list()->{$oid}; }
                }

                undef $w;
                $cv->send (\%oidsret);
            },
            -varbindlist => \@oids
        );
        my @result = $cv->recv;


        if (defined $result[0]) {
            foreach my $oid (@oids) {
                printf(" %s", $result[0]->{$oid});
            }
        } else {
            printf(" SNMP error");
        }

        printf("\n");
    }

}
Собственно всё как всегда, для AnyEvent - обёртка, callback, результат!
Для критиков. Безусловно, что вышеприведённый пример можно "оптимизировать". Например, получая результат $cv->recv за циклом обхода хостов, а через $cv->send передавать в результат более сложную структуру, которая бы содержала и имя хоста. Затем всю эту кухню разбирать. Но пример на то и пример чтобы над такими вещами не заморачиваться.

пʼятниця, 9 серпня 2013 р.

Преобразование IPv4-адресов в Perl

В дополнение к предыдущему, религиозно верному, решению по сортировке ip-адресов отдельно хочется отметить решение "из коробки" cpan - модуль Sort::Key::IPv4.
Установить его можно либо из репозитория дистрибутива Linux, либо непосредственно с cpan:
# cpan
cpan[1]> install Sort::Key::IPv4
CPAN: Storable loaded ok (v2.39)
Reading '/home/olden/.cpan/Metadata'
--- 8< --- skip --- 8< ---
  sudo /usr/bin/make install  -- OK

cpan[2]> exit
Возьмём наш предыдущий набор ip-адресов:
my @array = ("127.0.0.1","212.90.160.8", "10.100.175.11", "10.10.10.8", "212.90.160.33","212.90.160.40");
my %hash = ("127.0.0.1" => "1", "212.90.160.8" => "0", "10.100.175.11" => "1", "10.10.10.8" => "1", "212.90.160.33" => "0", "212.90.160.40" => [ "1", "2" ] );
И отсортируем его используя функционал модуля Sort::Key::IPv4
foreach my $ip ( ipv4sort @array ) {
    printf("%s\n", $ip);
}
и, соответственно, для ключей хеша:
foreach my $ip ( ipv4sort keys %hash ) {
    printf("%s => %s\n", $ip, $hash{$ip});
}

вівторок, 6 серпня 2013 р.

Преобразование IPv4-адресов в Perl

К примеру, имеем такие массив и хеш:
my @array = ("127.0.0.1","212.90.160.8", "10.100.175.11", "10.10.10.8", "212.90.160.33","212.90.160.40");
my %hash = ("127.0.0.1" => "1", "212.90.160.8" => "0", "10.100.175.11" => "1", "10.10.10.8" => "1", "212.90.160.33" => "0", "212.90.160.40" => [ "1", "2" ] );
Хотим:
  • научиться быстренько преобразовывать каждый ip-адрес либо в числовой вид, либо просто в набор из четырёх байт;
  • хотим быстро, без лишних накладных расходов, вывести отсортированные значения ip-адресов из массива;
  • также хотим быстро, без лишних накладных расходов, вывести отсортированные значения ip-адресов, которые являются ключами хеша.
Преобразования из ip-адреса в число, из ip-адреса в набор символов и обратно можно осуществить, например, следующим образом:
map { 
    # Преобразовать ip-адрес в число
    my $n = unpack("N",pack("C4",split /\./));

    # Преобразовать число в ip-адрес
    print join(".",unpack("C4",pack("N",$n))),"\n";

    # Преобразовать ip-адрес в набор символов
    my $c = pack("C4",split /\./);

    # Преобразовать набор символов в ip-адрес
    print join(".",unpack("C4", $c)),"\n";
} @array;

Для того чтобы вывести отсортированный массив ip-адресов очевидным, однако не самым эффективным, является следующее решение:
foreach my $ip ( sort {
    my @a = split /\./, $a; my @b = split /\./, $b;
    return $a[0] <=> $b[0] || $a[1] <=> $b[1] || $a[2] <=> $b[2] || $a[3] <=> $b[3];
    } @array ) {
    printf("%s\n", $ip);
}
Используем другое, более элегантное решение, выведем отсортированный массив ip-адресов, при используя преобразование GRT (Guttman-Rosler Transform) для того чтобы избежать вызова пользовательской функции в sort. Подробнее об этом можно прочитать в Pragmatic Perl — Выпуск 4. Июнь 2013 в статье "Сортировка в Perl".
foreach my $ip ( map { join(".",unpack("C4")) } sort map { pack("C4",split /\./) } @array ) {
    printf("%s\n", $ip);
}

Для того чтобы отсортировать по ключу хеша слегка преобразуем предыдущий цикл:
foreach my $ip ( map { join(".",unpack("C4")) } sort map { pack("C4",split /\./) } keys %hash ) {
    printf("%s => %s\n", $ip, $hash{$ip});
}


середа, 14 листопада 2012 р.

Обновить все установленные модули Perl с CPAN

Обновить с CPAN-а все установленные в системе perl-модули можно одной командой:
sudo perl -MCPAN -e 'CPAN::Shell->notest(install => CPAN::Shell->r)'
при этом останется лишь ответить на ряд вопросов и дождаться окончания процесса ;)

середа, 25 липня 2012 р.

Perl: сохраняем хэш (hash) в XML, считываем XML в хэш (hash)

Используем для этого модуль XML::Simple. Для дампа хэша используем Data::Dumper.
#!/usr/bin/perl

use strict;
use warnings;
use XML::Simple;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Terse = 1;
Имя XML-файла куда будем сохранять наш хэш:
my $conf_xml = 'serpol.xml';
Пример многоуровневого хэша:
my $routers = {
    "router0" => {
        user    => 'user0',
        password=> 'pass0',
        enable  => 'enab0',
        edgedev => {
            'switch00' => { type => "Cisco" },
            'switch01' => { type => "ExtremeNetworks" },
            'dslam0' => { type => "Alcatel 7324" }
        }
    },
    "router1" => {
        user    => 'user1',
        password=> 'pass1',
        enable  => 'enab1',
        edgedev => {
            'switch10' => { type => "Cisco" }
        }
    }
};
Вот таким вот образом мы сохраняем данные в XML-файл:
my $xml_os = XML::Simple->new();
open my $fh, '>:encoding(utf8)', $conf_xml or die "open($conf_xml): $!";
my $xml = $xml_os->XMLout( $routers,
    OutputFile => $fh,
    RootName => 'serpol',
    AttrIndent => 0,
    NoAttr => 0
);
close $fh;
undef $xml_os;
Вот, что у нас получилось:
<serpol>
  <router0 enable="enab0" password="pass0" user="user0">
    <edgedev name="dslam0" type="Alcatel 7324" />
    <edgedev name="switch00" type="Cisco" />
    <edgedev name="switch01" type="ExtremeNetworks" />
  </router0>
  <router1 enable="enab1" password="pass1" user="user1">
    <edgedev name="switch10" type="Cisco" />
  </router1>
</serpol>
А теперь прочитаем назад этот XML-файл в хэш:
my $xml_is = XML::Simple->new();
my $hash = $xml_is->XMLin( $conf_xml );
print Dumper( $hash );
undef $xml_is;
Дамп восстановленного хэша:
{
  'router1' => {
    'enable' => 'enab1',
    'password' => 'pass1',
    'user' => 'user1',
    'edgedev' => {
      'name' => 'switch10',
      'type' => 'Cisco'
    }
  },
  'router0' => {
    'enable' => 'enab0',
    'password' => 'pass0',
    'user' => 'user0',
    'edgedev' => {
      'dslam0' => {
        'type' => 'Alcatel 7324'
      },
      'switch01' => {
        'type' => 'ExtremeNetworks'
      },
      'switch00' => {
        'type' => 'Cisco'
      }
    }
  }
};

вівторок, 26 червня 2012 р.

Запрос к MSSQL на Perl из Linux

Собственно используем FreeTDS, /etc/freetds/freetds.conf:
[orion]
        host = 10.254.103.38
        port = 1433
        client charset = UTF-8
        tds version = 8.0
        text size = 20971520
Устанавливаем tdsodbc, unixodbc и libdbd-odbc-perl:
$ sudo aptitude install tdsodbc libdbd-odbc-perl unixodbc
Настраиваем UnixODBC, /etc/odbcinst.ini:
[FreeTDS]
Description = FreeTDS
Driver      = /usr/lib/odbc/libtdsodbc.so
Setup       = /usr/lib/odbc/libtdsS.so
UsageCount  = 1
Ну вот, теперь пишем запрос в Perl'е:
#!/usr/bin/perl -w

use strict;
use DBI;

my $dbh = DBI->connect('dbi:ODBC:server=orion;port=1433;driver=FreeTDS;tds_version=8.0', 'username', 'password', {PrintError => 0});
die "Unable for connect to server $DBI::errstr" unless $dbh;

my $rc;
my $sth;
    
#$sth = $dbh->prepare('select @@servername');
$sth = $dbh->prepare('SELECT [Caption] AS conn_details, 0 AS cnt_conn_details FROM [OrionDB].[dbo].[Nodes] GROUP BY [Caption] ORDER BY conn_details');
if($sth->execute) {
    while(my $dat = $sth->fetchrow_hashref) {
        foreach my $k (sort keys %{ $dat }) {
            print $k,"=>",${ $dat }{$k},"\n";
        }
    }
}

Чтение UTF16 в Perl

Попалась чудная программа, которая разработана под Windows и хранит свои данные хоть и в текстовом формате, но не в UTF8, который является привычным для Linux, а в UTF16.
Встала задача прочитать этот чудный файл в Perl'е, да так чтобы его содержимое было корректно воспринято.
Оказалось всё не просто, а очень просто:
foreach my $orionmap ( sort @orionmap ) {
    open my $FMAP, "<:encoding(utf16)", "$orionmap" || die "Can't open $orionmap for read: $!\n";
    while (<$FMAP>) {
        chomp;
        chop if /\r$/;
        print;
        print "\n";
    }
    close $FMAP;
}
Потом уже нашёл статью на Хабре где народ говорит о возможных граблях. Что-ж, как говорил один знакомый людоед: "Пожуём - увидим!".

вівторок, 28 лютого 2012 р.

Perl: какие модули установлены?

Как узнать какие дополнительные модули для Perl установлены?
Для начала, если не установлен, ставим perl-modules:
sudo aptitude install perl-modules
Затем рисуем небольшой скрипт:
#!/usr/bin/perl -w
use strict;
use ExtUtils::Installed;

my $instmod = ExtUtils::Installed->new();
foreach my $module ($instmod->modules()) {
    my $version = $instmod->version($module) || "-"; print "$module --> $version \r\n";
}
запускаем его и получаем результат примерно такого вида:
CGI::FastTemplate --> 1.09 
Convert::ASN1 --> 0.22 
Convert::ASN1::asn1c --> 0.07 
Cope --> - 
Data::Dumper --> 2.128 
Env::Path --> 0.18 
ExtUtils::CBuilder --> 0.2703 
ExtUtils::ParseXS --> 2.2206 
File::Slurp --> 9999.19 
File::Which --> 1.09 
IO::Tty --> 1.10 
IPC::Run --> 0.90 
IPC::Run3 --> 0.044 
Lingua::RU::PhTranslit --> 0.4 
Net::CSTA --> 0.04 
Net::CSTAv3::Client --> 0.05 
Net::SMTP::Server --> 1.1 
Net::SNMP --> v6.0.0 
Perl --> 5.10.0 
Probe::Perl --> 0.01 
Test::Harness --> 3.22 
Test::Script --> 1.07 
Test::Simple --> 0.98 
Thread::Synchronized --> 0.03 
YAML --> 0.71 

середа, 8 лютого 2012 р.

Perl: как сменить позицию курсора в окне терминала?

Используем Term::Cap (описание) и POSIX (описание, POSIX::Termios).
#!/usr/bin/perl -w

use strict;
use Term::Cap;

my $ospeed = 9600;

eval {
    # Получиь скорость вывода на терминал
    require POSIX;
    my $termios = new POSIX::Termios;
    $termios->getattr;
    $ospeed = $termios->getospeed;
};

# Инициализация терминала
my $terminal = Term::Cap->Tgetent({ TERM => undef, OSPEED => $ospeed });
$terminal->Trequire(qw/cm cl rc sc/);

# Запомнить позицию курсора
print $terminal->Tputs('sc', 1);

# Очистить экран
print $terminal->Tputs('cl', 1);

foreach my $x (1..10) {
    foreach my $y (1..10) {
        # Переместить курсор в нужную позицию
        my $goto = $terminal->Tgoto('cm', $x * 5, $y);
        print $goto, $x * $y;
    }
}

# Вернуть позицию курсора
print $terminal->Tputs('rc', 1);

вівторок, 15 листопада 2011 р.

Perl & GeoIP

Простенькая такая себенапоминалка о Perl и GeoIP:
# aptitude install libgeo-ip-perl
$ perl -e 'use Geo::IP; my $gi = Geo::IP->open("/usr/share/GeoIP/GeoIP.dat", GEOIP_STANDARD); print $gi->country_code_by_addr("212.90.160.40"), "\n";'
UA
$ perl -e 'use Geo::IP; my $gi = Geo::IP->open("/usr/share/GeoIP/GeoIP.dat", GEOIP_STANDARD); print $gi->country_code_by_addr("193.34.140.1"), "\n";'
UA
$ perl -e 'use Geo::IP; my $gi = Geo::IP->open("/usr/share/GeoIP/GeoIP.dat", GEOIP_STANDARD); print $gi->country_code_by_addr("8.8.8.8"), "\n";'
US
$ perl -e 'use Geo::IP; my $gi = Geo::IP->open("/usr/share/GeoIP/GeoIP.dat", GEOIP_STANDARD); print $gi->country_code_by_addr("8.8.4.4"), "\n";'
US