IPC::Open2 - 使用 open2() 打开一个用于读写进程
use IPC::Open2;
my $pid = open2(my $chld_out, my $chld_in,
'some', 'cmd', 'and', 'args');
# or passing the command through the shell
my $pid = open2(my $chld_out, my $chld_in, 'some cmd and args');
# read from parent STDIN and write to already open handle
open my $outfile, '>', 'outfile.txt' or die "open failed: $!";
my $pid = open2($outfile, '<&STDIN', 'some', 'cmd', 'and', 'args');
# read from already open handle and write to parent STDOUT
open my $infile, '<', 'infile.txt' or die "open failed: $!";
my $pid = open2('>&STDOUT', $infile, 'some', 'cmd', 'and', 'args');
# reap zombie and retrieve exit status
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
open2() 函数运行给定的命令,并连接 $chld_out 用于读取,$chld_in 用于写入。它是你尝试时应该起作用的东西
my $pid = open(my $fh, "|cmd args|");
$chld_in 文件句柄将开启自动刷新。
如果 $chld_out 是一个字符串(即,一个裸字文件句柄而不是一个 glob 或一个引用),并且它以 >&
开头,那么子进程将直接将输出发送到该文件句柄。如果 $chld_in 是一个以 <&
开头的字符串,那么 $chld_in 将在父进程中关闭,子进程将直接从它读取。在这两种情况下,将进行 dup(2) 而不是 pipe(2)。
如果读取器或写入器为空字符串或未定义,这将被替换为一个自动生成的句柄。如果是这样,你必须在参数槽中传递一个有效的左值,以便它可以在调用者中被覆盖,否则将抛出异常。
open2() 返回子进程的进程 ID。它在失败时不会返回:它只会引发与 /^open2:/
匹配的异常。但是,子进程中的 exec
失败不会被检测到。您需要自己捕获 SIGPIPE。
open2() 不会等待子进程退出并回收它。除了可以接受让操作系统处理此问题的简短程序外,您需要自己执行此操作。这通常与您完成进程后调用 waitpid $pid, 0
一样简单。未能执行此操作会导致积累失效或“僵尸”进程。有关更多信息,请参见 "perlfunc 中的 waitpid"。
整个事件非常危险,因为您可能会永远阻塞。它假设它将与类似于 bc(1) 的东西进行通信,既写入它又从中读取。这可能是安全的,因为您“知道”像 bc(1) 这样的命令将一次读取一行并一次输出一行。但是,像 sort(1) 这样的程序首先读取其整个输入流,非常容易导致死锁。
这种方法的主要问题是,如果您无法控制在子进程中运行的源代码,则无法控制它对管道缓冲区执行的操作。因此,您不能只打开一个到 cat -v
的管道,并不断地从中读取和写入一行。
CPAN 上的 IO::Pty 和 Expect 模块可以帮助解决这个问题,因为它们提供了一个真正的 tty(实际上是一个伪 tty),这使您能够在调用的命令中再次回到行缓冲。
参数的顺序与 open3() 不同。
有关处理 STDERR 的替代方法,请参见 IPC::Open3。此函数实际上只是 open3() 的包装器。