假设你的 R 程序是
#! /usr/bin/env r
require(Hmisc)
cat(argv[1], "\n")
结果出乎意料地健谈:
$ ./prog.r foo
加载所需的包:Hmisc
加载所需的包:方法
加载所需包:survival
加载所需的包:stats
加载所需的包:utils
加载所需包:图形
加载所需的包:样条
附件包:'Hmisc'
以下对象从 package:survival 中屏蔽:
untangle.specials
以下对象从 package:base 中屏蔽:
格式.pval,
round.POSIXt,
截断.POSIXt,
单位
富
从这里,您可以丢弃标准错误或将其与另一个流合并。
丢弃标准错误
放弃标准错误的一种方法是使用2>/dev/null 的shell 重定向。这是一个通用机制,2 是standard error's file descriptor。例如:
#! /usr/bin/perl
use warnings;
use strict;
open my $command_out, "-|", "./prog.r foo 2>/dev/null"
or die "$0: could not start prog.r";
while (<$command_out>) {
print "got: $_";
}
shell 也会处理backtick or qx// 表达式
#! /usr/bin/perl
use warnings;
use strict;
(my $command_out = `./prog.r foo 2>/dev/null`) =~ s/^/got: /mg;
print $command_out;
还有一个标量命令传递给system
#! /usr/bin/perl
use warnings;
use strict;
system("./prog.r foo 2>/dev/null") == 0
or warn "$0: prog.r exited " . ($? >>8);
对于所有这些,输出是
$ ./prog.pl
得到:foo
但有时您不希望外壳将其肮脏的手套放在您的命令上。也许它包含您不想处理转义的 shell 元字符或引号。这是 safe pipe-open 有用的时候:
#! /usr/bin/perl
use warnings;
use strict;
my $pid = open my $command_out, "-|";
die "$0: fork: $!" unless defined $pid;
if ($pid == 0) {
# child
open STDERR, ">", "/dev/null" or die "$0: open: $!";
exec "./prog.r", "foo & bar" or exit 1; # STDERR silent now
}
while (<$command_out>) {
print "got: $_";
}
close $command_out or warn "$0: prog.r exited " . ($? >> 8);
在"-|" 上打开一个句柄会派生一个孩子并将孩子的标准输出连接到该句柄。与fork 一样,它向子进程返回 0,向父进程返回非零进程标识符,或者在失败时返回未定义的值。
在 child 中,我们首先将 STDERR 重定向到 /dev/null,然后使用 exec 将 child 替换为我们的 R 程序。请注意,我们以列表形式传递命令以绕过 shell:
如果 LIST 中有多个参数,或者如果 LIST 是具有多个值的数组,则使用 LIST 中的参数调用 execvp(3)。
因为我们再也看不到标准错误,所以显式地close $command_out 以检查孩子是否快乐地跑很重要。否则,你会得到一个令人费解的静默失败。
示例运行:
$ ./prog.pl
得到:foo & bar
将STDERR 合并到STDOUT
要查看句柄上的标准错误,请改用2>&1,例如,
open my $command_out, "-|", "./prog.r foo 2>&1" or die;
通过安全管道打开,dup 将标准错误输出到标准输出:
if ($pid == 0) {
# child
open STDERR, ">&", \*STDOUT or die "$0: open: $!";
exec "./prog.r", "foo & bar" or die "$0: exec: $!";
}
open 文档涵盖了这一点:
您也可以在 Bourne shell 传统中指定一个以 >& 开头的 EXPR,在这种情况下,字符串的其余部分被解释为要被欺骗的文件句柄(或文件描述符,如果是数字)的名称( dup(2)) 并打开。
即使您可以通过这种方式查看标准错误,使用close 检查孩子的退出状态仍然是一个好主意。
现在一切都到达$command_out:
得到:加载所需的包:Hmisc
得到:加载所需的包:方法
得到:加载所需的包:生存
得到:加载所需的包:统计
得到:加载所需的包:utils
得到:加载所需的包:图形
得到:加载所需的包:样条
拿到:
得到:附加包:'Hmisc'
拿到:
拿到:
得到:以下对象从 package:survival 中屏蔽:
拿到:
得到: untangle.specials
拿到:
拿到:
得到:以下对象从 package:base 中屏蔽:
拿到:
得到:format.pval,
得到:round.POSIXt,
得到:trunc.POSIXt,
得到:单位
拿到:
得到:foo & bar