假设我运行一个命令或 shell 脚本,它会给出输出。在不了解此命令或 shell 脚本的内部结构的情况下,如何确定输出是来自stderr
还是stdout
?
例如,
$ ls -ld /
drwxrwxr-t 35 root admin 1258 Dec 11 19:16 /
对比
ls -ld /test
ls: /test: No such file or directory
如何确定第一个命令打印到stdout
,第二个命令打印到stderr
(是吗?)?
答案1
没有办法知道输出是否已被打印。在这种情况下,stdout
和都stderr
连接到终端,因此当文本出现在终端上时,有关写入哪个流的信息已经丢失;它们在到达终端之前就被程序组合在一起了。
在上述情况下,您可以做的是运行命令stdout
并stderr
重定向到不同的位置,看看会发生什么。或者运行两次,一次使用stdout
重定向到/dev/null
,一次使用stderr
重定向到/dev/null
,然后查看哪种情况会导致文本显示。
您可以通过在命令行末尾添加来重定向stdout
到,也可以通过添加 来重定向到。/dev/null
>/dev/null
stderr
/dev/null
2>/dev/null
答案2
您可以使用 重定向 stdout > file
,并使用 重定向 stderr 2> file
。许多现代 shell 支持重定向到命令,因此您可以使用sed
它来突出显示哪个输出来自哪个流:
$ ls 2> >(sed 's/^/2: /') > >(sed 's/^/1: /')
1: unity_support_test.0
1: vmwareDnD
$ ls foo 2> >(sed 's/^/2: /') > >(sed 's/^/1: /')
2: ls: cannot access foo: No such file or directory
答案3
annotate-output
来自 Debian 的脚本devscripts
让您有选择地执行此操作:
$ annotate-output ls -ld /test
14:54:22 -: Started ls -ld /test
14:54:22 E: ls: cannot access /test: No such file or directory
14:54:22 -: Finished with exitcode 2
第二列分别用O
和表示 stdout 和 stderr E
。
有一些警告,主要的警告如其他答案中所述:事后你不能这样做。尽管 shell 负责最初设置它们,但 shell 和终端都不知道任意程序如何使用其文件描述符。
此方法使用 fifo,写入 fifo 的行为与写入 tty 的行为不同,并且写入两个不同的 fifo 肯定是不同的(潜在的计时/交错问题)。此外,它不适合交互式使用,例如,这annotate-output bash
不是一个很好的计划,但它对于许多其他目的很有用。关于着色 stdin/stdout/stderr 的相关问题,有很多很多脚本和 shell 函数的示例,最强大的是标准德德它使用(大多数)程序的运行时修改来修改写入 stderr 的数据。
Anko 链接到的这个问题在相关主题上有很好的答案:对 stdout/stderr 输出进行着色: 我可以将 shell 配置为以不同颜色打印 STDERR 和 STDOUT 吗?
答案4
通常 STDERR 会将程序名称添加到消息前面并带有冒号。
例子:
rpm -zq some_utils
rpm: -zq: unknown option
VS
rpm -ql some_utils
package some_utils is not installed