如何从Perl脚本中捕获系统命令的stdin和stdout?

时间:2008-09-16 22:47:42

标签: perl ipc

在Perl脚本的中间,有一个我想要执行的系统命令。我有一个字符串,其中包含需要输入stdin的数据(该命令只接受来自stdin的输入),我需要捕获写入stdout的输出。我已经看过在Perl中执行系统命令的各种方法,open函数似乎是我需要的,除了它看起来我只能捕获stdin或stdout,而不是两者。

目前,似乎我最好的解决方案是使用open,将stdout重定向到临时文件,并在命令完成后从文件中读取。有更好的解决方案吗?

9 个答案:

答案 0 :(得分:6)

IPC :: Open2 / 3很好,但我发现通常我真正需要的只是IPC::Run3,它能够以最小的复杂度处理简单的案例:

use IPC::Run3;    # Exports run3() by default

run3( \@cmd, \$in, \$out, \$err );

该文档将IPC :: Run3与其他替代方案进行了比较。即使您不决定使用它,也值得一读。

答案 1 :(得分:3)

IPC :: Open3可能会做你想要的。它可以捕获STDERR和STDOUT。

http://metacpan.org/pod/IPC::Open3

答案 2 :(得分:3)

在脚本顶部的某处,包含

use IPC::Open2;

这将包括必要的模块,默认情况下通常与大多数Perl发行版一起安装。 (如果没有它,可以使用CPAN安装它。)然后,而不是打开,调用:

$pid = open2($cmd_out, $cmd_in, 'some cmd and args');

您可以将数据发送到$ cmd_in,然后通过读取$ cmd_out读取命令的输出,将数据发送到命令。

如果您还希望能够读取命令的stderr流,则可以使用IPC :: Open3模块。

答案 3 :(得分:3)

perlipc documentation涵盖了许多方法,包括IPC :: Open2和IPC :: Open3。

答案 4 :(得分:2)

我最近发现的一种非常简单的方法是 IPC::Filter模块。它可以让您非常直观地完成工作:

$output = filter $input, 'somecmd', '--with', 'various=args', '--etc';

注意如果你传递一个列表,它如何在不通过shell的情况下调用你的命令。它还可以合理地处理常见实用程序的错误。 (失败时,die s,使用STDERR中的文本作为错误消息;成功时,STDERR将被丢弃。)

当然,它不适合大量数据,因为它无法进行任何流处理;此外,错误处理可能不够精细,无法满足您的需求。但它使许多简单的案例真的真的简单。

答案 5 :(得分:1)

我想你想看看IPC::Open2

答案 6 :(得分:1)

有一个特殊的perl命令

open2()

可在以下网址找到更多信息:http://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html

答案 7 :(得分:0)

如果我只想要一行输出或想要将结果拆分为换行符以外的其他内容,我总是这样做:

my $result = qx( command args 2>&1 );  
my $rc=$?;  
# $rc >> 8 is the exit code of the called program.

if ($rc != 0 ) {  
    error();  
}  

如果您想处理多行响应,请将结果作为数组获取:

my @lines = qx( command args 2>&1 );  

foreach ( my $line ) (@lines) {  
    if ( $line =~ /some pattern/ ) {  
        do_something();  
    }  
}  

答案 8 :(得分:0)

如果您不想包含额外的套餐,则可以执行

open(TMP,">tmpfile");
print TMP  $tmpdata ;
open(RES,"$yourcommand|");
$res = "" ;
while(<RES>){
$res .= $_ ;
}

这与你的建议相反,但也应该有用。