Perl:检查shell是否重定向了文件句柄

Perl:检查shell是否重定向了文件句柄,perl,shell,file-io,file-descriptor,Perl,Shell,File Io,File Descriptor,我想测试我的perl程序是否被调用为: my_program.pl 3>&1 my_program.pl 3>/tmp/file my_program.pl 21>my.fifo 或: 因此,我需要一种在perl中测试shell是否打开了一个数字文件描述符的方法 背景 这是GNU并行的一个可能扩展。目前,GNU Parallel仅确保STDOUT和STDERR不混合,因此这将混淆输出: parallel 'echo begin {} >&3; sleep

我想测试我的perl程序是否被调用为:

my_program.pl 3>&1
my_program.pl 3>/tmp/file
my_program.pl 21>my.fifo
或:

因此,我需要一种在perl中测试shell是否打开了一个数字文件描述符的方法

背景

这是GNU并行的一个可能扩展。目前,GNU Parallel仅确保STDOUT和STDERR不混合,因此这将混淆输出:

parallel 'echo begin {} >&3; sleep 1; echo end >&3' ::: a b c 3>/tmp/file
然而,这不会发生,因为STDERR由GNU Parallel缓冲:

parallel 'echo begin {} >&2; sleep 1; echo end >&2' ::: a b c 2>/tmp/file
现在,不需要在未打开的文件句柄上花费资源。这将完全失败:

parallel 'echo begin {} >&3; sleep 1; echo end >&3' ::: a b c
所以,如果文件描述符3实际上被重定向到GNU Parallel之外,GNU Parallel应该只缓冲它。但我不知道如何在Perl中检测到这一点


在GNU/Linux上,我可以转到/proc/$$/fd并查看打开了哪些描述符,但我更喜欢不依赖于/proc/*/fd的解决方案。

事实证明,这相当简单:只需打开filedescriptor的filehandle。如果失败,则不会打开filedescriptor:

perl -e 'for (1..1000) { my $fh; if(open($fh,">&=$_")) {$fh{$_}=$fh }  } print map{"$_\n"} keys %fh'  3>/tmp/foo

小问题是bash在中使用了fd62和更高版本。事实证明这相当简单:只需打开filedescriptor的filehandle。如果失败,则不会打开filedescriptor:

perl -e 'for (1..1000) { my $fh; if(open($fh,">&=$_")) {$fh{$_}=$fh }  } print map{"$_\n"} keys %fh'  3>/tmp/foo

小问题是bash为什么使用FD62及以上版本?在每种情况下表现不同的实用程序是否会违反最基本的Unix原则?除了Unix原则之外,造成这种复杂性的原因是什么,为什么需要从外部选择文件描述符?您的示例中没有一个是在给定的描述符上打开文件的。您的示例假定
my_program
已打开它们,写入它们的任何内容都将重定向到给定的文件。实际上,他的示例确实打开了描述符3。程序是否使用它是另一个问题。为什么?在每种情况下表现不同的实用程序是否会违反最基本的Unix原则?除了Unix原则之外,造成这种复杂性的原因是什么,为什么需要从外部选择文件描述符?您的示例中没有一个是在给定的描述符上打开文件的。您的示例假定
my_program
已打开它们,写入它们的任何内容都将重定向到给定的文件。实际上,他的示例确实打开了描述符3。程序是否使用它是另一个问题。