Изучаем Perl

975b8bba

Использование процессов как дескрипторов файлов


Следующий способ запуска процесса — создание процесса, которий вигля-дит как дескриптор файла (аналогично библиотечной подпрограмме рореп(3), если ви с ней знакомы). Мы можем создать для процесса дескриптор файла, которий либо получает результат работы процесса, либо подает в него входные данные**. Ниже приведен пример создания дескриптора файла для процесса who(l). Поскольку зтот процесе вьщает результат, которий мы хотим прочитать, мы создаем дескриптор файла, открытый для чтения:

open(WHOPROC, "who 1"); # открнть who для чтения

Обратите внимание на вертикальную черту справа от who. Зта черта информирует Perl о том, что данная операция open относится не к имени файла, а к командо, которую необходимо запустить. Поскольку черта стоит справа от команди, данннй дескриптор файла открнвается для чтения. Зто означает, что предполагается прием данных со стандартного внвода команди who. (Стандартний ввод и стандартний вывод ошибок продолжают исполь-зоваться совместно с Perl-процессом.) Для остальной части программы дескриптор whoproc — зто просто дескриптор файла, которий открыт для

* На самом деле все не так просто. См. соответствующий ответ в разделе 8 сборника часто задаваемых вопросов по Perl ("Как перехватить stderr из внешней команды?"). Если у вас Perl версии 5.004, зтот сборник распространяется как обычная man-страница — в данном случас per/faq8( 1).

** Ho не одновременно. Примеры двунаправленной связи приведены в главе 6 книги Programming Perl и на man-странице рег1ірс(1).

чтения, что означает возможность вьшолнения над файлом всех обычных операций ввода-вывода. Вот как можно прочитать данные из команды who в

массив:

@whosaid = <WHOPROC>;

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

open(LPR,"|Ipr -Psiatewriter") ;

print LPR Srockreport;

close(LPR) ;

В атом случае после открытия lpr мы записываем в него данные и закриваєм данный файл. Открьггие процесса с дескриптором файла позволяет выполнять команду параллельно с Perl-программой. Задание для дескриптора файла команды close заставляет Perl-программу ожидать завершения процесса. Если дескриптор не будет закрыт, процесе может продолжаться даже после завершения Perl-программы.




Открытие процесса для записи предполагает, что стандартний ввод команды будет получен из дескриптора файла. Стандартний вывод и стандартний вивод ошибок используются зтим процессом совместно с Perl. Как и прежде, ви можете использовать переадресацию ввода-вивода в етиле /bin/sh. Вот как в нашем последнем примере можно отбрасивать сообщения об ошибках команди Ipr.

open(LPR,"|Ipr -Psiatewriter >/dev/null 2>&1");

С помощью операций >/dev/null обеспечивается отбраснвание стандартного вивода путем переадресации его на нулевое устройство. Операция 2>&1 обеспечивает передачу стандартного вивода ошибок туда, куда направляется стандартний вывод, позтому сообщения об ошибках также отбрасываются.

Можно даже обьединить все зти фрагменти программи и в результате получить отчет обо всех зарегистрированных пользователях, кроме Фреда:

open (WHO,"who[ ") ;

open (LPR,"|Ipr - Psiatewriter");

while (<WHO>) (

unless (/fred/) { # не показывать имя Фред print LPR $_:

> } close WHO;

close LPR;

Считивая из дескриптора who по одной строке, зтот фрагмент кода выводит в дескриптор lpr все строки, которне не содержат строкового значення fred. В результате на принтер внводятся только те строки, которне не содержат имени fred.

Вовсе не обязательно указывать в команде open только по одной команде за один прием. В ней можно задать сразу весь конвейєр. Например, следую-щая строка запускает процесе ls(l),

который передает свои результати по каналу в процесе tail(l), который, в свою очередь, передает свои результати в дескриптор файла who pr:

open(WHOPR, "Is I tail -r I");


Содержание раздела