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

Mat*_*ock 18 bash terminal io-redirection

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

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

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

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

Ste*_*ris 41

您使用的语法是错误的。

cmd &2>1 >file
Run Code Online (Sandbox Code Playgroud)

将被拆分为

cmd &
2>1 >file
Run Code Online (Sandbox Code Playgroud)

这会:

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

你想要的语法是:

cmd >file 2>&1
Run Code Online (Sandbox Code Playgroud)

操作顺序很重要。这会:

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

结果是stderrstdout都将被重定向到file.

在 中bash,更简单的非标准(因此我不推荐它,出于可移植性的考虑)语法cmd &> file做同样的事情。

  • 如果你的机器上有 `at` 命令并且有使用它的权限,那么你可以通过 `at now` 运行该命令。有关详细信息,请参阅联机帮助页。这将通过批处理机制运行命令,并且该进程将永远不会写入 tty。但是,总的来说,我不会担心这种边缘情况。通常只有需要交互并故意需要向用户显示内容的进程才会使用`/dev/tty`。 (5认同)

Mat*_*ock 12

有两个问题。

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

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

test.sh

#!/bin/bash

echo dada
echo edada 1>&2
echo ttdada >/dev/tty
Run Code Online (Sandbox Code Playgroud)

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

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

edada
ttdada
Run Code Online (Sandbox Code Playgroud)

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

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

所以我们做对了:

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

我们得到:

ttdada.

现在我们做“重定向stdout/dev/null”,然后“将标准错误重定向到标准输出指向的地方”(所以,/dev/null)。欢呼!

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