我对将stdout重定向到文件,然后将stderr重定向到stdout的常见方法比较熟悉。如果我运行ls > output.txt 2>&1
这样的命令,我猜外壳程序会在幕后执行类似下面的c代码:
close(1)
open("output.txt") // assigned to fd 1
close(2)
dup2(1, 2)
因为fd1已经被output.txt替换了,所以打印到stderr的任何东西都将被重定向到output.txt。但是,如果我运行ls 2>&1 > output.txt
,我猜会发生以下情况:
close(2)
dup2(1, 2)
close(1)
open("output.txt")
但是,由于ls > output.txt
在缺省情况下同时打印出stdout和stderr,那么shell和shell之间有什么不同呢?在这两种情况下,标准输出将被重定向到output.txt,而标准错误将被打印到控制台。
发布于 2020-02-24 16:14:39
使用ls >output.txt
,来自ls
的stderr
将转到从调用进程继承的stderr
。相比之下,使用ls 2>&1 >output.txt
时,ls
的stderr
被发送到调用进程的stdout
。
让我们用一个示例脚本来尝试一下,该脚本将一行输出分别打印到stdout
和stderr
$ cat pr.sh
#!/bin/sh
echo "to stdout"
echo "to stderr" 1>&2
$ sh pr.sh >/dev/null
to stderr
$ sh pr.sh 2>/dev/null
to stdout
现在,如果我们在第一个命令行中插入"2>&1“,看起来没有什么不同:
$ sh pr.sh 2>&1 >/dev/null
to stderr
但现在让我们在一个上下文中运行这两个命令,其中继承的stdout
位于控制台之外的其他位置:
$ (sh pr.sh 2>&1 >/dev/null) >/dev/null
$ (sh pr.sh >/dev/null) >/dev/null
to stderr
第二个命令仍然会打印,因为继承的stderr
仍然会转到控制台。但第一个不打印任何内容,因为"2>&1“将内部stderr
重定向到外部stdout
,该外部the将发送到/dev/null
。
虽然我从未使用过这种结构,但可以想象,在以下情况下(很可能是在脚本中),您希望运行一个程序,将其错误发送到一个文件,但将其错误转发给调用者,就好像它是“正常”输出一样,这可能是因为该程序与其他一些程序一起运行,而您希望第一个程序的“stdout
”输出与其他程序的“正常”输出属于同一个流。(也许两个程序都是编译器,您希望捕获所有错误消息,但它们在将错误发送到哪个流方面存在分歧。)
https://stackoverflow.com/questions/60360313
复制相似问题