为什么某些Linux程序的输出既不输出到STDOUT也不输出到STDERR?


21

为什么某些Linux程序的输出既不输出到STDOUT也不输出到STDERR?

实际上,我想知道如何可靠地捕获所有程序输出,无论它使用什么“流”。我的问题是某些程序似乎不让其输出被捕获。

一个示例是“时间”命令:

time sleep 1 2>&1 > /dev/null

real        0m1.003s
user        0m0.000s
sys         0m0.000s

要么

time sleep 1 &> /dev/null

real        0m1.003s
user        0m0.000s
sys         0m0.000s

为什么两次都看到输出?我希望所有这些都可以通过管道传递到/ dev / null

时间使用什么输出流,如何将其输出到文件中?

解决该问题的一种方法是创建一个Bash脚本,例如,combine.sh包含以下命令:

$@ 2>&1

然后可以以正确的方式捕获“时间”的输出:

combine.sh time sleep 1 &> /dev/null

(看不到输出-正确)

有没有不使用单独的组合脚本即可实现我想要的方法的方法?


3
首先你应该颠倒顺序:2>&1 > /dev/null指“2现在去到1变为(即终端,默认情况下),然后1现在去到/ dev / null的(但2还是到终端!)的使用。>/dev/null 2>&1说“ 1现在到达/ dev / null,然后2到达1所在的位置(即,也到达/ dev / null)。由于内置的​​“时间”不会被重定向,因此它在这里仍然无法正常工作,但通常更正确(例如,如果您使用/ usr / bin / time,它将可以工作)。将“ 2>&1”考虑为将1的“方向”复制为2,而不是将2复制为1
Olivier Dulac

Answers:


38

BashFAQ / 032中解决了这个问题。在您的示例中,您将:

{ time sleep 1; } 2> /dev/null

之所以

time sleep 1 2>/dev/null

不表现如何你希望是因为与句法,你要time的命令sleep 1 2>/dev/null(是的,命令sleep 1标准错误重定向到/dev/null)。内置函数以time这种方式工作,从而使这实际上成为可能。

bash 内建能真正做到这一点,因为......嗯,这是一个内建命令。对于time通常位于中的外部命令,这种行为是不可能的/usr/bin。确实:

$ /usr/bin/time sleep 1 2>/dev/null
$

现在,您问题的答案

为什么某些Linux程序的输出既不输出到STDOUT也不输出到STDERR?

是:是的,输出将输出到stdoutstderr

希望这可以帮助!


2
您可以创建其他fd和有命令明确地去那些(例如:在bash脚本: exec 3>/some/file ; ls >&3 ;
奥利维尔杜拉克

@OlivierDulac当然可以,或者使用coproc内置函数更简单。但是time内置的情况并非如此。
gniourf_gniourf

@ gniourf-gniourf:我之所以发表评论是因为您的句子“输出将输出到stdout或stderr” ^^
Olivier Dulac

14

您对特定问题time的内置已经回答了,但没有任何写一些命令stdoutstderr。一个典型的例子是Unix命令cryptcrypt不带参数的加密标准输入stdin并将其写入标准输出stdout。它使用来提示用户输入密码getpass(),默认情况下,它会向发出提示/dev/tty/dev/tty是当前的终端设备。写入将/dev/tty具有写入当前终端的效果(如果有,请参见isatty())。

crypt无法写入的原因stdout是因为它将加密的输出写入stdout。另外,最好提示输入/dev/tty而不是写入,stderr以便在用户重定向stdout和时stderr仍显示提示。(出于相同的原因,crypt由于密码stdin用于读取要加密的数据,因此无法从读取密码。)


2
+1。与OP的相关性较小,但与遇到的每个人都更相关“为什么某些linux程序的输出既不输出到STDOUT也不输出到STDERR?” 通过Google。:-)
ruakh

0

time sleep 1 > /dev/null 2>&1#重定向“ sleep's”的输出为空。然后,“时间”将写入自己的输出,而无需重定向。就像“ time (sleep 1 > /dev/null 2>&1)”。

(time sleep 1) > /dev/null 2>&1 #运行“ time sleep 1”,然后将其输出重定向为null。

[]秒


-1

您遇到的问题是重定向以另一种方式起作用。你写了

time sleep 1 2>&1 > /dev/null

这会将标准输出重定向到/dev/null,然后将标准错误重定向到标准输出。

要重定向所有输出,您必须编写

time sleep 1 > /dev/null 2>&1 

然后,将标准错误重定向到标准输出,然后将所有标准输出(包含标准错误)重定向到/dev/null


这不适用于内置 的bash time。请参阅我的答案以获得一些解释。
gniourf_gniourf

+1,因为这是对类似问题的有用答案。尽管@Olivier在上述问题的评论中对此进行了更好的解释。
Will Sheppard 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.