Анимация
JavaScript
|
Главная Библионтека При каждом выполнении этого цикла используется одна строка выходных данных команды who, потому что взятая в обратные кавычки команда интерпретируется в списочном контексте. Стандартный ввод и стандартный вывод ошибок команды, взятой в обратные кавычки, наследуются от Perl-процесса*. Это значит, что обычно стандартный вывод таких команд вы можете получить как значение строки, заключенной в обратные кавычки. Одна из распространенных операций - объединение стандартного вывода ошибок со стандартным выводом, чтобы команда в обратных кавычках "подбирала" их оба. Для этого используется конструкция shell 2>&l: die "rm spoke" if rm fred 2>41 ; Здесь Perl-процесс завершается, если rm посылает какое-нибудь сообщение - либо на стандартный вывод, либо на стандартный вывод ошибок, потому что результат больше не будет пустой строкой (пустая строка соответствовала бы значению "ложь"). Использование процессов как дескрипторов файлов Следующий способ запуска процесса - создание процесса, который выглядит как дескриптор файла (аналогично библиотечной подпрограмме рореп(З), если вы с ней знакомы). Мы можем создать для процесса дескриптор файла, который либо получает результат работы процесса, либо подает в него входные данные**. Ниже приведен пример создания дескриптора файла для процесса who( 1). Поскольку этот процесс выдает результат, который мы хотим прочитать, мы создаем дескриптор файла, открытый для чтения: open(whoproc, "who]"); # открыть who для чтения Обратите внимание на вертикальную черту справа от who. Эта черта информирует Perl о том, что данная операция open относится не к имени файла, а к команде, которую необходимо запустить. Поскольку черта стоит справа от команды, данный дескриптор файла открывается для чтения. Это означает, что предполагается прием данных со стандартного вывода команды who. (Стандартный ввод и стандартный вывод ошибок продолжают использоваться совместно с Perl-процессом.) Для остальной части программы дескриптор WHOPROC - это просто дескриптор файла, который открыт для На самом деле все не так просто См соответствующий ответ в разделе 8 сборника часто задаваемых вопросов по Perl ("Как перехватить stderr из внещней команды") Если у вас Peil версии 5 004, этот сборник распространяется как обычная man-страница - в данном случае perlfaq8(\) Но не одновременно Примеры двунаправленной связи приведены в главе 6 книги Programming Perl vi на тап-странице perlipc(l) чтения, что означает возможность выполнения над файлом всех обычных операций ввода-вывода. Вот как можно прочитать данные из команды who в массив: gwhosaid = <WHOPROC>; Аналогичным образом для запуска команды, которой необходимы входные данные, мы можем открыть дескриптор файла процесса для записи, поставив вертикальную черту слева от команды, например: open(LPR,"IIpr -Pslatewriter"); print LPR @rockreport; close (LPR) ; В этом случае после открытия LPR мы записываем в него данные и закрываем данный файл. Открытие процесса с дескриптором файла позволяет выполнять команду параллельно с Peri-программой. Задание для дескриптора файла команды close заставляет Perl-программу ожидать завершения процесса. Если дескриптор не будет закрыт, процесс может продолжаться даже после завершения Perl-программы. Открытие процесса для записи предполагает, что стандартный ввод команды будет получен из дескриптора файла. Стандартный вывод и стандартный вывод ошибок используются этим процессом совместно с Perl. Как и прежде, вы можете использовать переадресацию ввода-вывода в стиле /Ып/sh. Вот как в нашем последнем примере можно отбрасывать сообшения об ошибках команды Ipr. open(LPR,"IIpr -Pslatewriter >/dev/null 2>S1"); С помощью операции >/dev/null обеспечивается отбрасывание стандартного вывода путем переадресации его на нулевое устройство. Операция 2>&1 обеспечивает передачу стандартного вывода ошибок туда, куда направляется стандартный вывод, поэтому сообщения об ошибках также отбрасываются. Можно даже объединить все эти фрагменты программы и в результате получить отчет обо всех зарегистрированных пользователях, кроме Фреда: open (WHO, "who I " ) ; open (LPR,"IIpr - Pslatewriter"); while {<WH0>) { unless (/fred/) f # не показывать имя Фред print LPR close WHO; close LPR; Считывая из дескриптора who по одной строке, этот фрагмент кода выводит в дескриптор LPR все строки, которые не содержат строкового значения fred. В результате на принтер выводятся только те строки, которые не содержат имени fred. Вовсе не обязательно указывать в команде open только по одной команде за один прием. В ней можно задать сразу весь конвейер. Например, следующая строка запускает процесс ls(l), который передает свои результаты по каналу в процесс tail(l), который, в свою очередь, передает свои результаты в дескриптор файла whopr: open(WHOPR, "Is 1 tail -г i"); Использование функции fork Еще один способ создания нового процесса - клонирование текущего Perl-процесса с помощью UNIX-функции fork. Функция fork делает то же самое, что и системный вызов fork(2): создает клон текущего процесса. Этот клон (он называется порожденным процессом, а оригинал - родительским) использует тот же выполняемый код, те же переменные и даже те же открытые файлы. Различаются эти два процесса по возвращаемому значению функции fork: для порожденного процесса оно равно нулю, а для родительского - ненулевое (или undef, если этот системный вызов окажется неудачным). Ненулевое значение, получаемое родительским процессом,- это не что иное как идентификатор порожденного процесса. Вы можете проверить возвращаемое значение и действовать соответственно: if (I defined($child pid = forkO) f die "cannot fork: $"; ! elsif (?pid) ( # я - родительский процесс > else ( # я - порожденный процесс Чтобы максимально эффективно использовать этот клон, нам нужно изучить еще несколько функций, которые весьма похожи на своих UNIX-тезок: это функции wait, exit и exec. Самая простая из них - функция exec. Это почти то же самое, что и функция system, за тем исключением, что вместо запуска нового процесса для выполнения shell-команды Perl заменяет текущий процесс на shell. После успешного выполнения exec Perl-программа исчезает, поскольку вместо нее выполняется затребованная программа. Например, exec "date"; заменяет текущую Perl-программу командой date, направляя результат этой команды на стандартный вывод Perl-программы. После завершения команды date делать больше нечего, потому что Perl-программа давно исчезла. Все это можно рассматривать и по-другому: функция system похожа на комбинацию функции fork с функцией exec, например: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 [ 59 ] 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |