为什么某些 Linux 程序的输出既不输出到 STDOUT 也不输出到 STDERR?
实际上,我想知道如何可靠地捕获所有程序输出,无论它使用什么“流”。我遇到的问题是某些程序似乎不允许捕获其输出。
一个例子是‘time’命令:
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。
时间使用什么输出流,以及如何将其传输到文件中?
解决该问题的一种方法是创建一个猛击脚本,例如,combine.sh
包含以下命令:
$@ 2>&1
然后就可以以正确的方式捕获“时间”的输出:
combine.sh time sleep 1 &> /dev/null
(没有看到输出-正确)
有没有一种方法可以在不使用单独的组合脚本的情况下实现我想要的效果?
答案1
这个问题在Bash常见问题/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?
是:确实如此,输出到标准输出或者标准错误。
希望这可以帮助!
答案2
你关于内置的特定问题time
已经得到解答,但是是有些命令既不写入stdout
也不写入stderr
。一个典型的例子是 Unix 命令crypt
. crypt
不带参数加密标准输入stdin
并将其写入标准输出stdout
。它使用以下命令提示用户输入密码getpass()
,默认情况下会将提示输出到/dev/tty
。 /dev/tty
是当前终端设备。写入/dev/tty
相当于写入当前终端(如果有,请参阅isatty()
)。
crypt
无法写入的原因stdout
是它将加密输出写入stdout
。此外,最好提示/dev/tty
而不是写入 ,stderr
这样如果用户重定向stdout
和stderr
,仍然可以看到提示。(出于同样的原因,crypt
无法从 读取密码stdin
,因为它正用于读取要加密的数据。)
答案3
time sleep 1 > /dev/null 2>&1
# 将“sleep”的输出重定向为 null。然后,“time”会写入自己的输出,无需重定向。它就像“ time (sleep 1 > /dev/null 2>&1)
”。
(time sleep 1) > /dev/null 2>&1
# 运行“time sleep 1”,然后将其输出重定向为空。
[]秒
答案4
您的问题在于重定向以另一种方式工作。您写道
time sleep 1 2>&1 > /dev/null
这会将标准输出重定向到/dev/null
,然后将标准错误重定向到标准输出。
要重定向所有输出,你必须编写
time sleep 1 > /dev/null 2>&1
然后标准错误将被重定向到标准输出,之后所有标准输出(包含标准错误)将被重定向到/dev/null
。