Friday, August 04, 2006
subshell в PERL
Моя задача сегодня - сделать так, чтобы один из скриптов имел возможность выполнять какие-либо команды на локальной или удаленной машине. Причем не просто команды, а инлайн перл- и шелл-скрипты (генерируемые на лету), причем их довольно много, а выполнять надо часто, поэтому system() и `` отпадают сразу хотя бы из соображений быстродействия.
Итак, в глубинах CPAN отыскалось следующее:
- IPC::Open2: Вроде бы получалось запускать (в режиме неблокирующего чтения), но это довольно сложно: во-первых, надо было еще обойти все глюки с буфферизацией ввода-вывода и не наплодить при этом своих, и во-вторых у меня не получилось корректно завершить процесс - хотя бы перехватить Ctrl-C
- Expect.pm: Практически идеальный вариант. Все программирование сводится к установке своих обработчиков на появление тех или инных сообщений от запущенной программы. В будущем я скорей всего еще воспользуюсь этим модулем, но в данном случае он не подходит, поскольку для его работы нужен отдельный pty, а этот ресурс может и не быть доступен в тех услових, в которых придется работать моей программе.
- IPC::Session: Это обертка вокруг IPC::Open3, которая с точки зрения пользователя ведет себя как Excpect.pm - это мой выбор! Я пока не знаю, чего я лишился, отказавшись от Excpect, который работает через отдельный pty, но пока мне это кажется самым удобным вариантом. :)
- Net::SSH::Perl: к сожалению, этот модуль не заработал на моей машине (FreeBSD 4.11) - зависает во время тестирования один из зависимых модулей. По идее, Net::SSH - это аналог open3, но работающий с удаленной консолью, а Net::SSH::Perl - это IPC::Session-подобный интерфейс. Количество зависимостей и размер Bundle::SSH устрашают, но, судя по документации - вполне подходящий вариант.