2011-04-26 24 views
1

我使用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 "\n\n answer: $answer"; 

对我来说这很奇怪,反引号似乎从来没有任何问题。其他一切,包括examples in C++ from MSDN

我怀疑IPC :: Open2的问题和C++中的例子(与上面的链接有关)与我将命令外壳(cmd.exe)中的STDIN和STDOUT重定向以及孩子进程(psexec)在与我的远程系统通信时做同样的事情。

此外,在perldocs中,我可以找到有关反引号如何工作的详细信息?我最感兴趣的是他们在Windows上的“内幕”。或者,在Perl源代码中,我可以查看反引号的内部工作原理(可能比我咀嚼的东西还要咬人,但在这一点上值得一试)。

UPDATE: 继安迪的建议,我发现这工作:

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 "\n\n answer: @answer"; 

waitpid($pid, 0); 
my $child_exit_status = $? >> 8; 
+1

您是否在尝试读取输出('my $ answer = <$chld_out>'')之前调用'waitpid'? – Andy 2011-04-26 16:23:12

+0

哇,这使它工作。我不知道为什么! – Mick 2011-04-26 16:27:17

回答

2

我还不是很了解它是如何工作的窗口,所以也许有人可以提供更具体的答案,但之间的管道时perl进程中,你需要小心避免不希望的阻塞和死锁。在perlipc中对各种问题情况进行了一些讨论。

在您的示例中,立即致电waitpid会导致问题。一种可能性是孩子在读取输出之前无法退出,所以一切都会暂停,因为父母不会读取输出。另一种可能性是部分数据流作为waitpid调用的一部分被关闭,这会导致远程进程出现问题。

在任何情况下,最好在调用waitpid之前读取子进程的输出。

相关问题