Анимация
JavaScript
|
Главная Библионтека 16.4. Чтение или запись в другой программе 563 При вызове с одним аргументом, не содержащим метасимволов, аргумент разбивается по пропускам и затем интерпретируется так, словно функция exec была вызвана для полученного списка: ехес("archive accounting.data") or die "Couldnt replace myself with archive: $\n", Комментарий Функция Perl exec обеспечивает прямой интерфейс к системной функции ехес1р(2), которая заменяет текущую программу другой без изменения идентификатор процесса. Программа, вызвавшая exec, стирается, а ее место в таблице процессов операционной системы занимает программа, указанная в качестве аргумента exec, В результате новая программа сохраняет тот же идентификатор процесса ($$), что и у исходной программы. Если указанную программу запустить не удалось, exec возвращает false, а исходная программа продолжает работу. Не забывайте проверять такую ситуацию. При переходе к другой программе с помощью exec не будут автоматически вызваны ни блоки END, ни деструкторы объектов, как бы это произошло при нормальном завершении процесса. !> Смотри также- Описание функции exec в perlfunc(i); страница руководства ехес1р(2) вашей системы (если есть); рецепт 16.2. 16.4. Чтение или запись в другой программе Проблема Вы хотите запустить другую программу и либо прочитать ее вывод, либо предоставить входные данные. Решение Вызовите open с символом в начале или конце строки. Чтобы прочитать вывод программы, поставьте в конце: $pid = open(REAOME, "program arguments ") or die Couldnt fork. $!\n, while (<README>) { # .. . close(README) or die Couldnt close $\n", Чтобы передать данные, поставьте в начале: $pid = open(WRITEME, " program arguments") or die "Couldnt fork: $!\n", print WRITEME "data\n"; close(WRITEME) or die Couldnt close: $i\n", Комментарий При чтении происходящее напоминает , разве что на этот раз у вас имеется идентификатор процесса и файловый манипулятор. Функция open также использует командный интерпретатор, если встречает в аргументе метасимволы, и не использует в противном случае. Обычно это удобно, поскольку вы избавляетесь от хлопот с расширением метасимволов в именах файлов и перенаправлением ввода/вывода. Однако в некоторых ситуациях это нежелательно. Конвейерные вызовы open, в которых участвуют непроверенные пользовательские данные, ненадежны при работе в режиме меченых данных или в ситуациях, требующих абсолютной уверенности. Рецепт 19.6 показывает, как имитировать эффект конвейерных вызовов open без риска, связанного с использованием командного интерпретатора. Обратите внимание на явный вызов close для файлового ма1пшулятора. Когда функция open используется для подключения файлового манипулятора к порожденному процессу, Perl запоминает этот факт и при закрытии манипулятора автоматически переходит в ожидание. Если порожденный процесс к этому моменту не завершился, Perl ждет, пока это произойдет. Иногда ждать приходится очень, очень долго: $pid = open(F, sleep 100000 ), # Производный процесс приостановлен close(F), # Родитель надолго задумался Чтобы избежать этого, уничтожьте производный процесс по значению PID, полученному от open, или воспользуйтесь конструкцией pipe-f огк-ехес (см. рецепт 16.10) При попытке записать данные в завершившийся процесс, ваш процесс получит сигнал SIGPIPE. По умолчанию этот сигнал убивает ваш процесс, поэтому программист-параноик на всякий случай установит обработчик SIGPIPE. Если вы хотите запустить другую программу и предоставить содержимое ее STDIN, используется аналогичная конструкция: $pid = open(WRITEME, program args ), print WRITEME hello\n , » Программа получит hello\n в STDIN close(WRITEME), # Программа получит EOF в STDIN Символ I в начале аргумента функции open, определяющего имя файла, сообщает Perl о необходимости запустить другой процесс. Файловый манипулятор, открытый функцией open, подключается к STDIN порожденного процесса. Все, что вы запишете в этот манипулятор, может быть прочитано процессом из STDIN После закрытия манипулятора (close) при следующей попытке чтения из STDIN порожденный процесс получит eof. Описанная методика может применяться для изменения нормального вывода вашей программы. Например, для автоматической обработки всех данных утилитой постраничного вывода используется фрагмент вида: Spager = SENVfPAGER} /usr/bin/less , # XXX может не существовать open(STDOUT, Spager ), Теперь все данные, направленные в стандартный вывод, будут автоматически проходить через утилиту постраничного вывода. Вам не придется исправлять другие части программы. 16.5. Фильтрация выходных данных 565 Как и при открытии процесса для чтения, в тексте, передаваемом командному интерпретатору, происходит расширение метасимволов. Чтобы избежать обращения к интерпретатору, следует воспользоваться решением, аналогичным приведенному выше. Как и прежде, родитель должен помнить о close. При закрытии файлового манипулятора, подключенного к порожденному процессу, родитель блокируется до заверщения потомка. Если порожденный процесс не завершается, то и закрытие не произойдет. Приходится либо заранее убивать порожденный процесс, либо использовать низкоуровневый сценарий pipe-fork-exec. При использовании сцепленных открытий всегда проверяйте значения, возвращаемые open и close, не ограничиваясь одним open. Дело в том, что возвращаемое значение open не говорит о том, была ли команда успешно запущена. При сцепленном открытии команда выполняется вызовом fork для порожденного процесса. Если возможности создания процессов в системе не исчерпаны, fork немедленно возвращает PID порожденного процесса. К тому моменту, когда порожденный процесс пытается выполнить команду exec, он уже является самостоятельно планируемым. Следовательно, если команда не будет найдена, практически не существует возможности сообщить об этом функции open, поскольку она принадлежит другому процессу! Проверка значения, возвращаемого close, позволяет узнать, успешно ли выполнилась команда. Если порожденный процесс завершается с ненулевым кодом (что произойдет в случае, если команда не найдена), то close возвращает false, а переменной присваивается статус ожидания процесса. Об интерпретации содержимого этой переменной рассказано в рецепте 16.2. t> Смотри также- Описание функции open вperlfunc(l); рецепты 16.10; 16.15; 16.19; 19.6. 16.5. Фильтрация выходных данных Проблема Требуется обработать выходные данные вашей программы без написания отдельного фильтра. Решение Присоедините фильтр с помощью разветвляющего (forking) вызова open. Например, в следующем фрагменте вывод программы ограничивается сотней строк: heacl(IOO), while (о) { print, sub head { my $lines = shift 20, return If $pid = open(ST00UT, - ), 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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 [ 182 ] 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |