要将stderr和stdout合并到stdout流中,我们将其附加到命令中:

2>&1

例如,查看编译g++main.cpp时的前几个错误:

g++ main.cpp 2>&1 | head

2>&1的详细含义是什么?


当前回答

注意,1>&2不能与2>&1互换使用。

假设您的命令依赖于管道,例如:docker日志1b3e97c49e39 2>&1|grep“一些日志”grepping将在stderr和stdout之间发生,因为stderr基本上被合并到stdout中。

但是,如果您尝试:docker日志1b3e97c49e39 1>&2|grep“一些日志”,grepping根本不会在任何地方搜索,因为Unix管道通过连接stdout|stdin来连接进程,而在第二种情况下,stdout被重定向到stderr,Unix管道对此没有兴趣。

其他回答

你需要从管道的角度来理解这一点。

$ (whoami;ZZZ) 2>&1  | cat
logan
ZZZ: command not found

正如您所看到的,管道LHS的stdout和stderr都被送入(管道的)RHS。

这与

$ (whoami;ZZZ) |& cat
logan
ZZZ: command not found

人们,永远记住paxdiablo关于重定向目标当前位置的提示。。。这很重要。

我对2>&1运算符的个人记忆是这样的:

将&视为“和”或“添加”的意思(字符是一个“与”,不是吗?)因此它变成:“将2(stderr)重定向到1(stdout)已经/当前所在的位置,并添加两个流”。

同样的助记符也适用于其他常用的重定向,1>和2:

思考含义并或添加。。。(你知道安培符号是什么意思吗?)因此它变成:“将1(stdout)重定向到2(stderr)已经/当前所在的位置,并添加两个流”。

请记住:您必须从“末尾”、从右到左(而不是从左到右)读取重定向链。

unix命令2>&1

这用于将错误打印到终端。

当产生错误时,它们将被写入内存地址&2的“标准错误”缓冲区,以及来自该缓冲区的2个引用和流。当产生输出时,它们被写入“标准输出”缓冲区的内存地址&1,以及来自该缓冲区的1个引用和流。

所以回到指挥部。每当程序unix_commands产生错误时,它都会将其写入错误缓冲区。因此,我们创建一个指向缓冲区2的指针,并将>错误重定向到输出缓冲区&1。此时我们就完成了,因为输出缓冲区中的任何内容都由终端读取和打印。

如果系统上不存在/foo,而/tmp确实存在…

$ ls -l /tmp /foo

将打印/tmp的内容并为/foo打印错误消息

$ ls -l /tmp /foo > /dev/null

将/tmp的内容发送到/dev/null并为/foo打印错误消息

$ ls -l /tmp /foo 1> /dev/null

将完全相同(注意1)

$ ls -l /tmp /foo 2> /dev/null

将打印/tmp的内容并将错误消息发送到/dev/null

$ ls -l /tmp /foo 1> /dev/null 2> /dev/null

将向/dev/null发送列表和错误消息

$ ls -l /tmp /foo > /dev/null 2> &1

是速记

该构造将标准错误流(stderr)发送到标准输出(stdout)的当前位置——其他答案似乎忽略了这个货币问题。

您可以使用此方法将任何输出句柄重定向到另一个,但它最常用于将stdout和stderr流引导到单个流中进行处理。

例如:

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

请注意,最后一个命令不会将stderr重定向到outfile2,而是将其重定向到遇到参数时的stdout(outfile1),然后将stdout重定向到outile2。

这允许一些相当复杂的诡计。