Shell 什么';“command>;输出`和`命令2>&;1>;输出`?

Shell 什么';“command>;输出`和`命令2>&;1>;输出`?,shell,operating-system,Shell,Operating System,我对将stdout重定向到一个文件,然后将stderr重定向到stdout的常用方法有些熟悉。 如果我运行一个命令,比如ls>output.txt 2>&1,我猜在引擎盖下,shell正在执行类似以下c代码的操作: close(1) open("output.txt") // assigned to fd 1 close(2) dup2(1, 2) 由于fd 1已被output.txt替换,因此打印到stderr的任何内容都将重定向到output.txt。 但是,如果我运行ls 2>&1>ou

我对将stdout重定向到一个文件,然后将stderr重定向到stdout的常用方法有些熟悉。 如果我运行一个命令,比如
ls>output.txt 2>&1
,我猜在引擎盖下,shell正在执行类似以下c代码的操作:

close(1)
open("output.txt") // assigned to fd 1
close(2)
dup2(1, 2)
由于fd 1已被output.txt替换,因此打印到stderr的任何内容都将重定向到output.txt。 但是,如果我运行
ls 2>&1>output.txt
,我猜会发生以下情况:

close(2)
dup2(1, 2)
close(1)
open("output.txt")

但是,由于shell默认同时打印stdout和stderr,因此
ls 2>&1 output.txt
ls>output.txt
之间有什么区别吗?在这两种情况下,stdout将被重定向到output.txt,而stderr将被打印到控制台。

使用
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
,这将
/dev/null


虽然我从未使用过这种结构,但可以想象,在(在脚本中,很可能)您希望运行程序的情况下,它可能会很有用,您可以将其
stdout
发送到一个文件,但将其
stderr
转发给调用方,就好像它是“正常”输出一样,可能是因为该程序正在与其他一些程序一起运行,并且您希望第一个程序的“错误”输出与其他程序的“正常”输出是同一流的一部分。(可能这两个程序都是编译器,您希望捕获所有错误消息,但它们不同意将错误发送到哪个流。)

默认情况下,您的终端会打印stdout和stderr。它们仍然是分开的溪流。