Perl:open3 但对于 n 个文件描述符
Posted
技术标签:
【中文标题】Perl:open3 但对于 n 个文件描述符【英文标题】:Perl: open3 but for n file descriptors 【发布时间】:2013-07-15 17:15:48 【问题描述】:open3 只接受 STDIN、STDOUT 和 STDERR。如果正在运行的命令使用其他文件描述符,则 open3 无法捕获这些:
echo foo # Can be captured
echo foo >&2 # Can be catured
echo foo >&3 # Cannot be captured (with open3)
我已经研究过 IPC::Run::run 似乎能够处理这个问题,但我也需要 PID,但我发现 IPC::Run::run 没有办法给我。
是否有一个 openN 或 IPC::Run::run 方法可以给我 PID?
背景
这是用于 GNU Parallel 的可能扩展,因此您可以这样做:
parallel 'echo start >&3;sleep 10;echo end >&3' ::: a b c 3>out.file
无需混合来自不同作业的输出。 GNU Parallel 需要跟踪每个 pid - 尤其是在使用 --keep-order
时。
【问题讨论】:
你为什么要这个 pid? IPC::Open3 不会阻止您在 fd3 上放置管道。它只是不会为你做。 孩子的 pid 在 IPC::Run 内部是已知的。只需将IPC::Run::run
替换为IPC::Run::start
并转储返回的对象。不幸的是,这没有记录在案,所以你自己......
@ikegami 如果您以echo start >&3;sleep 10;echo end >&3
作为正在运行的命令并将 fd3 分配给 perl 文件句柄来发布答案,我将接受它作为答案。
【参考方案1】:
fd3 已经存在,所以你需要做的就是确保孩子继承它。由于它是继承的,因此您根本不需要做任何事情。
$ perl -e'
system "echo foo >&3";
' 3>bar
$ cat bar
foo
但是如果你想确保它是继承的,你可以使用下面的
$ perl -e'
use Fcntl qw( F_GETFD F_SETFD FD_CLOEXEC );
if (open(my $fh, ">&=", 3))
my $flags = fcntl($fh, F_GETFD, 0)
or die $!;
fcntl($fh, F_SETFD, $flags & ~FD_CLOEXEC)
or die $!;
system "echo foo >&3";
' 3>bar
$ cat bar
foo
【讨论】:
我不希望它继承。我想把孩子在 fd3 上打印的所有内容放在一个文件中,当孩子死时,在 fd3 上打印文件。我知道如何做最后一部分(孩子死后打印)。 请记住,在 GNU Parallel 中,我可以让多个孩子同时写入每个他们的 fd3,并且我不希望输出混合,因此 GNU Parallel 需要在输出到达之前捕获它GNU Parallel 的 fd3。 如果你可以制作 open4(fd0,fd1,fd2,fd3,cmd,arg) 并基于 open3 那就没问题了。以上是关于Perl:open3 但对于 n 个文件描述符的主要内容,如果未能解决你的问题,请参考以下文章
Perl 行为差异关闭由 open() 产生的子进程与 IPC::Open3
perl IPC:Open3 最小通过 perlcritic?