在 perl 中打开管道时直接 STDERR
我正在使用 open( my $command_out, "-|", $command_string )
来执行命令并即时处理其输出(不必先等待命令完成,如 <代码>系统())。
我注意到,当我以这种方式调用一些 R 脚本时,一些 R 消息会打印到屏幕上(例如 正在加载所需的包:...
)。我猜这是因为 R 将此输出发送到 stderr (?尽管这些并不是真正的错误)。
当 open()
时,是否可以将此输出也定向到 $command_out
以便屏幕保持干净?
I am using open( my $command_out, "-|", $command_string )
to execute a command and process its output on the fly (not having to wait for the command to finish first, as in system()
).
I noticed that when I call some R scripts this way, some of R messages are printed to the screen (e.g. Loading required package: ...
). I guess this is because R sends this output to stderr (? although these are not really errors).
Is it possible to direct this output too to $command_out
when open()
-ing so the screen will remain clean?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
假设您的 R 程序结果
出人意料地喋喋不休:
从这里,您可以丢弃标准错误或将其与另一个流合并。
丢弃标准错误
丢弃标准错误的一种方法是使用 shell 重定向
2>/dev/null
。这是一个通用机制,2 是标准错误的文件描述符。例如:shell 还将处理 反引号或
qx//
表达式和标量命令传递给
system
对于所有这些,输出为
但有时您不希望 shell 将其肮脏的手套放在您的命令上。也许它包含您不想处理转义的 shell 元字符或引号。这是安全管道打开有用的时候:
打开
"-|"
分叉一个子进程并将子进程的标准输出连接到该句柄。与fork
一样,它向子进程返回 0,一个非-父进程的零进程标识符,或失败时的未定义值。在子进程中,我们首先将
STDERR
重定向到/dev/null
,然后使用exec
将子程序替换为我们的 R 程序。请注意,我们以列表形式传递命令来绕过 shell:因为我们无法再看到标准错误,所以显式
关闭 $command_out
以检查子进程是否运行愉快非常重要。否则,您会遇到令人费解的无声失败。示例运行:
将
STDERR
合并到STDOUT
要查看句柄上的标准错误,请改用
2>&1
,eg< /em>,通过安全的管道打开,
dup
将标准错误输出到标准输出:open
文档涵盖了这一点:尽管您可以通过这种方式看到标准错误,但使用
close
检查子进程的退出状态仍然是一个好主意。现在一切都通过
$command_out
到达:Say your R program is
which turns out to be surprisingly chatty:
From here, you could discard the standard error or merge it with another stream.
Discarding the standard error
One way to discard the standard error is to use a shell redirect of
2>/dev/null
. This is a general mechanism, and 2 is the standard error's file descriptor. For example:The shell will also process backtick or
qx//
expressionsand a scalar command passed to
system
For all of these, the output is
But sometimes you don't want the shell putting its grubby mitts on your command. Maybe it contains shell metacharacters or quotes that you don't want to deal with escaping. This is when a safe pipe-open is useful:
Opening a handle on
"-|"
forks a child and connects the child's standard output to that handle. Likefork
, it returns 0 to the child, a non-zero process identifier to the parent, or the undefined value on failure.In the child, we first redirect
STDERR
to/dev/null
and then useexec
to replace the child with our R program. Note that we passed the command in list form to bypass the shell:Because we can't see the standard error any longer, it's important to explicitly
close $command_out
to check that the child ran happily. Otherwise, you'd get a puzzling silent failure.Sample run:
Merge
STDERR
intoSTDOUT
To see the standard error on your handle, use
2>&1
instead, e.g.,With a safe pipe-open,
dup
the standard error onto the standard output:The
open
documentation covers this:Even though you can see the standard error this way, it's still a good idea to check the child's exit status with
close
.Now everything arrives over
$command_out
:一个简单的方法是将 2>&1 附加到 $command_string,但这是否有效取决于您的 shell。 (例如,解释 $command_string 的 shell)
An easy way is to append 2>&1 to $command_string, but whether or not this works will depend on your shell. (eg, the shell that interprets $command_string)
使用
IPC::Run
分别捕获 STDOUT 和 STDERR。pump
函数为您提供即时输出。Use
IPC::Run
to capture STDOUT and STDERR separately. Thepump
function gives you the output on the fly.也许您可以将整个程序的 STDERR 重定向到 STDOUT ?
Maybe you could redirect STDERR to STDOUT for the whole program?
做叉子和执行自己:
}
Do fork & exec yourself:
}