显然我不知道所有可用的输出目的地。我知道stdout
( &1
) 和stderr
(&2
)。但是,在重定向两个描述符之后,我有时仍然在我的控制台中获取一些输出!
我能想到的最简单的例子是 GNU Parallel;每次我使用它时,我都会看到一条引用通知。即使我这样做了&2>1 > file
,我仍然会看到该通知。
这同样适用于emerge
:当我运行emerge并且出现一些问题时,一些信息不会打印到stdout
nor stdin
,因为我重定向了它们并且它们仍然可以通过。
我主要通过使用来解决这些问题script
,但我仍然想知道是什么导致了这个问题。
答案1
您使用的语法是错误的。
cmd &2>1 >file
将被拆分为
cmd &
2>1 >file
这会:
cmd
作为后台作业运行,没有重定向- 在一个单独的进程中(没有命令!)将重定向
stderr
到一个字面上调用的文件1
并重定向stdout
到file
您想要的语法是:
cmd >file 2>&1
操作顺序很重要。这会:
- 重定向
stdout
至file
- 重定向
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
因为求值的顺序是从左到右,所以我们首先得到“重定向stderr
到stdout
正在输出的地方(因此,控制台输出)”。然后我们得到“重定向stdout
到” /dev/null
。我们最终会遇到这样的情况:
stdout
-> /dev/null
stderr
-> 控制台
所以我们得到了正确的结果:
./testmyscript.sh >/dev/null 2>&1
我们得到:
ttdada
。
现在我们执行“重定向stdout
到/dev/null
”,然后“将 stderr 重定向到 stdout 指向的位置”(所以,/dev/null
)。欢呼!
然而,我们仍然有一个问题;程序打印到/dev/tty
.现在我不知道如何解决这种行为,因此您很可能需要script
,但希望这种行为不会经常发生。