简体   繁体   English

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

[英]How can I capture the stdin and stdout of system command from a Perl script?

In the middle of a Perl script, there is a system command I want to execute. 在Perl脚本的中间,有一个我想要执行的系统命令。 I have a string that contains the data that needs to be fed into stdin (the command only accepts input from stdin), and I need to capture the output written to stdout. 我有一个字符串,其中包含需要输入stdin的数据(该命令只接受来自stdin的输入),我需要捕获写入stdout的输出。 I've looked at the various methods of executing system commands in Perl, and the open function seems to be what I need, except that it looks like I can only capture stdin or stdout, not both. 我已经看过在Perl中执行系统命令的各种方法, open函数似乎是我需要的,除了它看起来我只能捕获stdin或stdout,而不是两者。

At the moment, it seems like my best solution is to use open , redirect stdout into a temporary file, and read from the file after the command finishes. 目前,似乎我最好的解决方案是将open ,redirect stdout用于临时文件,并在命令完成后从文件中读取。 Is there a better solution? 有更好的解决方案吗?

IPC::Open2/3 are fine, but I've found that usually all I really need is IPC::Run3 , which handles the simple cases really well with minimal complexity: IPC :: Open2 / 3很好,但我发现通常我真正需要的只是IPC :: Run3 ,它可以很好地处理简单的情况并且复杂度最低:

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

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

The documentation compares IPC::Run3 to other alternatives. 该文档将IPC :: Run3与其他替代方案进行了比较。 It's worth a read even if you don't decide to use it. 即使您不决定使用它,也值得一读。

IPC::Open3 would probably do what you want. IPC :: Open3可能会做你想要的。 It can capture STDERR and STDOUT. 它可以捕获STDERR和STDOUT。

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

Somewhere at the top of your script, include the line 位于脚本顶部的某处,包含该行

use IPC::Open2;

That will include the necessary module, usually installed with most Perl distributions by default. 这将包括必要的模块,默认情况下通常安装大多数Perl发行版。 (If you don't have it, you could install it using CPAN.) Then, instead of open, call: (如果没有它,可以使用CPAN安装它。)然后,而不是打开,调用:

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

You can send data to your command by sending it to $cmd_in and then read your command's output by reading from $cmd_out. 您可以通过将数据发送到$ cmd_in将数据发送到命令,然后通过从$ cmd_out读取来读取命令的输出。

If you also want to be able to read the command's stderr stream, you can use the IPC::Open3 module instead. 如果您还希望能够读取命令的stderr流,则可以使用IPC :: Open3模块。

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

A very easy way to do this that I recently found is the IPC::Filter module . 我最近发现的一个非常简单的方法是使用IPC :: Filter模块 It lets you do the job extremely intuitively: 它可以让您非常直观地完成工作:

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

Note how it invokes your command without going through the shell if you pass it a list. 注意如果你传递一个列表,它如何在不通过shell的情况下调用你的命令。 It also does a reasonable job of handling errors for common utilities. 它还可以合理地处理常见实用程序的错误。 (On failure, it die s, using the text from STDERR as its error message; on success, STDERR is just discarded.) (失败时,它会die ,使用STDERR中的文本作为错误消息;成功时,STDERR就会被丢弃。)

Of course, it's not suitable for huge amounts of data since it provides no way of doing any streaming processing; 当然,它不适合大量数据,因为它无法进行任何流处理; also, the error handling might not be granular enough for your needs. 此外,错误处理可能不够精细,无法满足您的需求。 But it makes the many simple cases really really simple. 但它使许多简单的案例非常简单。

我想你想看看IPC :: Open2

There is a special perl command for it 有一个特殊的perl命令

open2()

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

I always do it this way if I'm only expecting a single line of output or want to split the result on something other than a newline: 如果我只想要一行输出或想要将结果拆分为换行符以外的其他内容,我总是这样做:

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

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

If you want to deal with a multi-line response, get the result as an array: 如果要处理多行响应,请将结果作为数组获取:

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

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

If you do not want to include extra packages, you can just do 如果您不想包含额外的包,您可以这样做

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

which is the contrary of what you suggested, but should work also. 这与你的建议相反,但也应该有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何让Perl脚本接受来自STDIN和命令行参数的参数? - How can I get a Perl script to accept parameters from both STDIN and command line arguments? 如何重新初始化Perl的STDIN / STDOUT / STDERR? - How can I reinitialize Perl's STDIN/STDOUT/STDERR? 我可以从标准输入运行 Perl 脚本吗? - Can I run a Perl script from stdin? perl 如何将 perl 脚本的列表形式系统调用的 STDOUT 附加到文件 - perl how can I append STDOUT of list form system call of perl script to a file 我可以从 perl 进程中捕获 STDOUT 写入事件吗? - Can I capture STDOUT write events from a process in perl? 如何运行只能写入STDOUT并从STDIN读取的脚本? - How to run a script that can only write to STDOUT and read from STDIN? 如何使用别名修改Perl脚本中使用的系统命令? - How can I modify a system command used in Perl script with aliases? 从perl运行python脚本,带有stdin参数并保存stdout输出 - Running python script from perl, with argument to stdin and saving stdout output Perl脚本来捕获反引号中执行的命令的stderr和stdout - Perl script to capture stderr and stdout of command executed in back-quotes 如何强制 perl 仅从 stdin 而不是从命令行上的文件处理 args? - How can I force perl to process args ONLY from stdin and not from a file on command line?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM