#perl #winapi
#perl #winapi
Вопрос:
Я использую Perl для выполнения psexec и захвата выходных данных с консоли. Что мне кажется странным, так это то, что когда я выполняю команду с обратными метками, она каждый раз корректно фиксирует вывод.
Например, этот скрипт на Perl работает, и я использовал его в течение многих лет во многих различных конфигурациях:
use strict;
my @out;
@out = `psexec \\192.168.1.105 -u admin -p pass netstat -a`;
print @out;
Этот сценарий Perl завершается с ошибкой и, похоже, надежно приводит к зависанию psexesvc в удаленной системе:
use IPC::Open2;
my($chld_out, $chld_in, $pid);
$pid = open2($chld_out, $chld_in, 'psexec \\192.168.1.105 -u admin -p pass netstat -a');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
my $answer = <$chld_out>;
print "nn answer: $answer";
Что для меня так странно, так это то, что у обратных ссылок, похоже, никогда не возникает никаких проблем. Все остальное делает, включая примеры на C из MSDN.
Я подозреваю, что проблема с IPC:: Open2 и примером на C (ссылка выше) связана с тем фактом, что я перенаправляю STDIN и STDOUT из командной оболочки (cmd.exe ), и дочерний процесс (psexec) делает то же самое при обмене данными с моей удаленной системой.
Кроме того, где в perldoc я могу найти подробную информацию о том, как работают обратные ссылки? Меня больше всего интересуют их «внутренности» в Windows.
Или, где в исходном коде Perl я могу просмотреть внутреннюю работу backticks (возможно, это отнимает больше времени, чем я могу прожевать, но на данный момент стоит попробовать).
ОБНОВЛЕНИЕ: следуя предложению Энди, я обнаружил, что это работает:
use IPC::Open2;
my($chld_out, $chld_in, $pid);
$pid = open2($chld_out, $chld_in, 'psexec \\192.168.1.105 -u admin -p pass netstat -a');
my @answer = <$chld_out>;
print "nn answer: @answer";
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
Комментарии:
1. Вы пробовали читать выходные данные (
my $answer = <$chld_out>
) перед вызовомwaitpid
?2. Вау, это заставляет его работать. Хотя я понятия не имею, почему!
Ответ №1:
Я очень мало знаю о том, как это работает в Windows, поэтому, возможно, кто-нибудь сможет дать более конкретный ответ, но при передаче между процессами в perl вам нужно быть осторожным, чтобы избежать нежелательных блокировок и взаимоблокировок. В perlipc обсуждаются различные проблемные сценарии.
В вашем примере немедленный вызов waitpid
вызывает проблемы. Одна из возможностей заключается в том, что дочернее приложение не может завершить работу, пока что-то не прочитает выходные данные, поэтому все зависает, поскольку родительское приложение не собирается считывать выходные данные. Другая возможность заключается в том, что часть потока данных отключается как часть waitpid
вызова, и это вызывает проблему с удаленным процессом.
В любом случае, было бы лучше прочитать выходные данные дочернего процесса перед вызовом waitpid
.