程序如何输出到 STDOUT/STDERR 之外的其他地方?如何避免呢?

程序如何输出到 STDOUT/STDERR 之外的其他地方?如何避免呢?

显然我不知道所有可用的输出目的地。我知道stdout( &1) 和stderr(&2)。但是,在重定向两个描述符之后,我有时仍然在我的控制台中获取一些输出!

我能想到的最简单的例子是 GNU Parallel;每次我使用它时,我都会看到一条引用通知。即使我这样做了&2>1 > file,我仍然会看到该通知。

这同样适用于emerge:当我运行emerge并且出现一些问题时,一些信息不会打印到stdoutnor stdin,因为我重定向了它们并且它们仍然可以通过。

我主要通过使用来解决这些问题script,但我仍然想知道是什么导致了这个问题。

答案1

您使用的语法是错误的。

cmd &2>1 >file

将被拆分为

cmd &
2>1 >file

这会:

  1. cmd作为后台作业运行,没有重定向
  2. 在一个单独的进程中(没有命令!)将重定向stderr到一个字面上调用的文件1并重定向stdoutfile

您想要的语法是:

cmd >file 2>&1

操作顺序很重要。这会:

  1. 重定向stdoutfile
  2. 重定向stderr&1- 即相同的文件句柄stdout

结果是stderr和都stdout将被重定向到file.

在 中bash,更简单的非标准语法(出于可移植性的原因,我不推荐它)cmd &> file执行相同的操作。

答案2

有两个问题。

第一个是顺序很重要,第二个是/dev/tty

让我们使用此脚本作为我们想要捕获输出的示例脚本:

test.sh:

#!/bin/bash

echo dada
echo edada 1>&2
echo ttdada >/dev/tty

现在让我们看看命令的输出:

./testmyscript.sh 2>&1 >/dev/null:

edada
ttdada

因为求值的顺序是从左到右,所以我们首先得到“重定向stderrstdout正在输出的地方(因此,控制台输出)”。然后我们得到“重定向stdout到” /dev/null。我们最终会遇到这样的情况:

stdout-> /dev/null stderr-> 控制台

所以我们得到了正确的结果:

./testmyscript.sh >/dev/null 2>&1

我们得到:

ttdada

现在我们执行“重定向stdout/dev/null”,然后“将 stderr 重定向到 stdout 指向的位置”(所以,/dev/null)。欢呼!

然而,我们仍然有一个问题;程序打印到/dev/tty.现在我不知道如何解决这种行为,因此您很可能需要script,但希望这种行为不会经常发生。

相关内容