Monday, August 31, 2009

Perl: как определить, из какого модуля импортирована функция

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

В этом нам поможет модуль Devel::Peek. Делаем дамп ссылки на интересующую функцию и смотрим параметр GVGV::GV:

$ perl -MEncode -MDevel::Peek -e 'Dump &encode'
...
GVGV::GV = 0x284a9d48 "Encode" :: "encode"
...
В качестве альтернативы можно использовать Sub::Identify.

Если нет возможности установить эти модули, можно использовать такой подход: последовательно добавляем () ко всем выражениям use Module, пока не получим ошибку "Undefined subroutine ...".

Кстати, интересно, почему в пропиареную Perl Best Practices не включена хорошая практика: всегда использовать синтаксис use Module LIST вместо use Module, явно перечисляя имена импортируемых функций.

Sunday, August 30, 2009

Об аутентификации в mysql

MySQL снова удивил.
Допустим, нам надо добавить пользователя и разрешить ему доступ с любого хоста. По памяти набираю:

CREATE USER 'user'@'%' IDENTIFIED BY 'pass';
GRANT ALL PRIVILEGES ON mybd.* TO 'user'@'% WITH GRANT OPTION;

Вроде бы все ок. Тестируем с локального хоста, получаем 'Access denied'.

С паролями все ОК - хэш в таблице `user` совпадает с PASSWORD('pass'). В чем же дело ?

Таблица `user` сортируется перед использованием. Причем сперва по полю 'Host', потом 'User'.
Просмотр таблицы идет до первой подходящей записи. Поэтому в примере выше будет использоваться
запись ''@localhost а не 'user'@'%'. Для того чтобы можно было зайти с любого хоста, придется добавить
еще одну запись:

GRANT ALL PRIVILEGES ON mydb.* TO 'user'@'localhost' WITH GRANT OPTION;

Интересно, используется ли подобный алгоритм в других СУБД. Если кто в курсе - черкните в комменты.

Saturday, August 29, 2009

How::Do::I::Alias::This::Package::Name

Простой способ создания алиасов для перловых классов с именами типа Really::Long::Package::Names::You::Cant::Remember

use Really::Long::Package::Names::You::Cant::Remember;
sub MyRemember () { 'Really::Long::Package::Names::You::Cant::Remember' }

my $object = MyRemember->new; 

Достоинства этого метода:
  1. Никаких заморочек с нэймспейсами.
  2. Алиас подставляется на этапе компиляции (constant function), т.е. потерь в производительности нет.
  3. Ну и меньше печатания :-)
See also: aliased

На заметку (bash)

Чтобы заныкать какую-нить длинную команду (или просто текст) в history не выполняя её, набираем команду и нажимаем
ESC, # (или Ctrl-A, #, Enter). Впоследствии можно вернуться к этой команде, удалить знак комментария вначале и выполнить её.

Wednesday, August 26, 2009

Садистские упражнения

В предыдущем посте я писал, как меня напрягают админы использующие для частных сетей (с выходом в инет)
произвольные адреса. Как и следовало ожидать, в вопросах администрирования у таких "спецов" тоже несколько своеобразный подход. Несколько примеров, замеченных мной на РЕАЛЬНЫХ рабочих серверах.

Sunday, August 23, 2009

Perl: short-circuit operators

Логические short-circuit операторы - это те, которые определяют истинность выражения, вычисляя наименьшее число операндов, достаточное для определения значения выражения. Это отличает их от операторов, которые вычисляют значение всех элементов в выражении (например, & и | в Java).

В Perl такими операторами являются:&& , and , || и or. Пример:

open my $fh, '<', "input.txt" or die $!;


В отличие, например, от C, в Perl данные операторы возвращают не 0 или 1, а последнее вычисленное значение. Это позволяет писать выражения вроде:

$home = $ENV{HOME} || (getpwuid($<))[7] || die "You're homeless!n";


Возвращаемое значение определяется аналогично также в Python/Ruby/Javascript (но не в PHP %). Подробнее тут.

Индукция

Что можно сказать о "системном администраторе", между прочим неплохо оплачиваемом, который назначает в локальной офисной сети адреса 172/8? Как минимум:
  1. C данным документом он явно не знаком. И вообще не задавался вопросом, а какие собственно IP-адреса принято назначать локальным сетям.


  2. В анамнезе скорей всего будет присутствовать офисная или домашняя сеть 172.16/12. (Или 172/8, настроенная такими же псевдоадминами).

Thursday, August 20, 2009

Perl: прототипы встроенных функций

Функция sprintf при передаче ей массива в качестве аргумента ведет себя не так, как printf:
sub test1 { printf @_        }
sub test2 { print sprintf @_ }

test1 "%s", "ok"; # prints "ok"
test2 "%s", "ok"; # prints "2"

Всё потому, что sprintf в отличие от printf имеет прототип $@:
perl -le 'print "$_ - ".prototype $_ for ("CORE::sprintf", "CORE::printf")'
CORE::sprintf - $@
CORE::printf -


Соответственно, свой первый аргумент sprintf использует в скалярном контексте. Эта особенность упоминается в perldoc:

Unlike printf, sprintf does not do what you probably mean when you pass it an array as your first argument. The array is given scalar context, and instead of using the 0th element of the array as the format, Perl will use the count of elements in the array as the format, which is almost never useful.


Как вариант, вторую функцию можно переписать так:
sub test2 { print sprintf shift, @_ }

Wednesday, August 19, 2009

Любопытство

Недавно получил простой вопрос - где логически находится DNS-resolver (e.g. это часть приложения, часть операционной системы, etc.)? Я как то сходу и не ответил, т.к. системным программированием не занимался. Но как человек любопытный, решил немного покопаться в манах своей рабочей FreeBSD.

Thursday, August 13, 2009

рабочее

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

Оказывается этому даже учат в умных книжках, типа "Code Complete", которой я никогда не читал.
Тут более подробно об этом подходе.

Saturday, August 8, 2009

dyndns

Понадобилось мне привязать к своему домашнему компу (с динамическим IP) доменное имя.
Как оказалось, это легко сделать используя ресурсы вроде dyndns.com. Согласно доке на сайте, настройка сводится к следующим пунктам:

  1. Настраиваем сервис, к которому нужно получить доступ.
  2. Настраиваем форвардинг портов (если надо).
  3. Тестируем доступность сервиса извне.
  4. Создаем аккаунт на dyndns.com, выбираем доменное имя.
  5. Устанавливаем клиента для обновления нашей DNS-записи.
В качестве клиента я установил ddclient. A тут можно даже автоматически сгенерить для него конфиг. Лепота...