在外壳中,“ 2>&1”是什么意思?


2281

在Unix shell中,如果我想合并stderrstdout放入stdout流中以进行进一步的操作,则可以在命令末尾附加以下内容:

2>&1

因此,如果要head在的输出上使用g++,可以执行以下操作:

g++ lots_of_errors 2>&1 | head

因此我只能看到前几个错误。

我总是很难记住这一点,而且我经常不得不去查找它,这主要是因为我不完全理解这个特殊技巧的语法。

有人可以分解并逐字解释什么2>&1 意思吗?


50
@dbr我不认为这只是猛击-我相信这是一个波恩壳的东西;因此,sh,bash,ksh,灰,破折号等
枪支

8
这是重定向段落的一部分,该段落描述了POSIX兼容的shell,简称POSIX shell。例如,ksh是POSIX shell。请参阅:pubs.opengroup.org/onlinepubs/009695399/utilities/...
吉姆·麦克纳马拉

12
此构造也可在Windows上使用。
Vadzim 2013年

2
通常2>&12> / dev / null更好;-)
F. Hauri 2013年

11
我以为我要提到的|&2>&1 |您使用zsh的简写。我不能说这是否适用于其他类似bourne的shell或仅zsh功能。
chrixian 2013年

Answers:


2553

文件描述符1是标准输出(stdout)。
文件描述符2是标准错误(stderr)。

这是一种记住此构造的方法(尽管它并不完全准确):首先,2>1看起来像是重定向stderr到的好方法stdout。但是,它实际上将被解释为“重定向stderr到名为1” 的文件。&表示后面的是文件描述符而不是文件名。因此该构造变为:2>&1


280
但是那不应该&2>&1吗?
dokaspar

319
@Dominik:不,&在重定向的上下文中仅解释为“文件描述符”。写入command &2>&被解析为command &2>&1,即“ command在后台运行,然后运行命令2并将其标准输出重定向到其标准输出”。
亚当·罗森菲尔德

15
他们为什么选择这种神秘的东西?只是好奇。
CommaToast 2014年

81
但是,如何将stderr重定向到名为“&1”的文件?
马丁·菲克斯曼(MartínFixman)

120
@马丁:2>'&1'

631
echo test > afile.txt

将stdout重定向到afile.txt。这和做的一样

echo test 1> afile.txt

要重定向stderr,请执行以下操作:

echo test 2> afile.txt

>& 是将流重定向到另一个文件描述符的语法-0为stdin,1为stdout和2为stderr。

您可以通过执行以下操作将stdout重定向到stderr:

echo test 1>&2 # or echo test >&2

或相反亦然:

echo test 2>&1

因此,简而言之... 2>将stderr重定向到一个(未指定的)文件,追加&1将stderr重定向到stdout。


5
这对您有意义吗,java ... 2&1 >> data.log我看到我的一位同事做到了吗?
唐潘

5
@Harry看起来像不是bash的外壳或错字.. cmd 2>&1 >> somefile.log会将stdout / stderr附加到文件中-与上面的基本相同,并>> file附加
dbr

73
@dbr cmd 2>&1 >>file不会将stderr重定向到文件,但是cmd >> file 2>&1可以。顺序很重要。在第一种情况下,将stderr重定向到shell的stdout(如果以交互方式输入命令,则可能是tty),然后将stdout定向到该文件。在第二种情况下,将stdout定向到文件,然后将stderr定向到同一位置。
威廉·珀塞尔

2
我喜欢上面的答案,但可能会更清晰。“ 2>&1”将stderr重定向到stdout的目标。因此,如果您有类似“ ls -l >> directoryContents 2>&1”的名称,结果将是一个名为directoryContents的文件,并将工作目录的内容附加到该文件中。如果执行中有任何错误:错误消息也会在发生时附加到directoryContents文件中。
Max West

1
0(or 1,2)>&0(or 1,2)像一个选项来控制输出?是echo test >test.log 2>&1一样的echo test 2>&1 >test.log吗?
Simin Jie

318

有关重定向的一些技巧

关于此的某些语法特殊性可能具有重要的行为。有一个关于重定向,一些小的样本STDERRSTDOUT和参数排序

1-覆盖还是附加?

符号>均值重定向

  • >表示发送到一个完整的完整文件,如果存在则覆盖目标(请参阅稍后的#3noclobber bash功能)。
  • >>意思是除了发送之外,还会附加到目标(如果存在)。

无论如何,如果文件不存在,则会创建该文件。

2- Shell命令行取决于顺序!!

为了测试这一点,我们需要一个简单的命令,该命令将在两个输出上发送一些信息

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(当然,希望您没有名为的目录/tnt;)。好吧,我们有!!

因此,让我们看看:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

最后一个命令行转储STDERR到控制台,这似乎不是预期的行为...但是...

如果要对一个输出,另一个输出或两个输出进行后期过滤

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

请注意,本段的最后一个命令行与上一段完全相同,在那段我写的似乎不是预期的行为(因此,这甚至可能是预期的行为)。

嗯,关于重定向,在两个输出上执行不同的操作有一些技巧 :

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

注意:&9由于,描述符会自发出现) 9>&2

附录:nota!随着新版本>4.0)有一种新功能和更性感的语法可用于执行此类操作:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

最后是这样的级联输出格式:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

附录:nota!两种方式都具有相同的新语法:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

STDOUT经过一个特定的过滤器,STDERR另一个最后两个输出通过第三命令过滤合并去。

3-关于noclobber选项和>|语法

那是关于覆盖

set -o noclobber指示bash 不要覆盖任何现有文件时,该>|语法使您可以克服此限制:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

现在,文件每次都会被覆盖:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

通过>|

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

取消设置此选项和/或查询是否已设置。

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4-最后一招等等

为了重定向给定命令的两个输出,我们看到正确的语法可能是:

$ ls -ld /tmp /tnt >/dev/null 2>&1

对于这种特殊情况,有一个快捷语法:&>...或>&

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

注意:如果2>&1存在,1>&2也是正确的语法:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b-现在,我将让您考虑:

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c-如果您对更多信息感兴趣

您可以点击以下内容阅读精美的手册:

man -Len -Pless\ +/^REDIRECTION bash

在一个 安慰 ;-)


5
进一步阅读:如果您喜欢这样做,您可能会喜欢:重定向滥用如何产生奇怪的行为
F. Hauri 2013年


130

我发现了这篇关于重定向的精彩文章:关于重定向的全部信息

将标准输出和标准错误都重定向到文件

$命令&>文件

这种单线使用&>操作员将两个输出流-stdout和stderr-从命令重定向到文件。这是Bash的快捷方式,用于将两个流快速重定向到相同的目的地。

在Bash重定向两个流之后,文件描述符表如下所示:

在此处输入图片说明

如您所见,stdout和stderr现在都指向file。因此,写入stdout和stderr的所有内容都会写入file

有两种方法可以将两个流重定向到相同的目的地。您可以一个接一个地重定向每个流:

$命令>文件2>&1

这是将两个流都重定向到文件的更常见的方法。首先将stdout重定向到文件,然后将stderr复制为与stdout相同。因此,两个流最终都指向file

当Bash看到多个重定向时,它将从左到右对其进行处理。让我们看一下步骤,看看如何发生。在运行任何命令之前,Bash的文件描述符表如下所示:

在此处输入图片说明

现在,Bash处理第一个重定向>文件。我们之前已经看过了,它使stdout指向文件:

在此处输入图片说明

Next Bash看到第二个重定向2>&1。我们之前从未见过这种重定向。这将文件描述符2复制为文件描述符1的副本,我们得到:

在此处输入图片说明

这两个流都已重定向到文件。

但是在这里要小心!写作

命令>文件2>&1

与写作不同:

$命令2>&1>文件

重定向的顺序在Bash中很重要!此命令仅将标准输出重定向到文件。stderr仍将打印到终端。要了解为什么会发生这种情况,让我们再次执行这些步骤。因此,在运行命令之前,文件描述符表如下所示:

在此处输入图片说明

现在,Bash从左到右处理重定向。它首先看到2>&1,因此将stderr复制到stdout。文件描述符表变为:

在此处输入图片说明

现在,Bash看到了第二个重定向,>file并将标准输出重定向到文件:

在此处输入图片说明

你看到这里发生了什么吗?Stdout现在指向文件,但是stderr仍然指向终端!写入stderr的所有内容仍会打印到屏幕上!因此,请务必非常小心重定向的顺序!

另请注意,在Bash中,

$命令&>文件

与以下内容完全相同:

$命令>&file


3
如果“命令”以数字结尾,则后两个是不同的,因为这将作为>&
MM

非常好的绘图和解释!您能解释一下“重复”的真正含义吗?您提到:“这个[2>&1]将文件描述符2复制为文件描述符1的副本”。听起来好像stderr被复制到stdout。但是,如果是这样,我还应该看到err /dev/tty0吗?
HCSF

87

数字指的是文件描述符(fd)。

  • 零是 stdin
  • 一个是 stdout
  • 二是 stderr

2>&1 将fd 2重定向到1。

如果程序使用它们,那么它适用于任意数量的文件描述符。

您可以看看/usr/include/unistd.h是否忘记了它们:

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

就是说,我已经编写了使用非标准文件描述符进行自定义日志记录的C工具,因此除非将其重定向到文件或其他内容,否则您将看不到它。


58

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

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

一些例子是:

# 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)时的状态,然后重定向stdoutoutfile2

这允许一些相当复杂的欺骗。


5
尽管最后一个示例更加清楚:foo> outfile2 2> outfile1
Michael Cramer,2009年

3
清楚一点,是的,但是不会显示重定向的“位置”性质。该示例是人为设计的,因为通常在一行中执行此操作通常无济于事-当不同方负责重定向的不同部分时,该方法将变得非常有用。例如,当脚本执行一小部分重定向,而您又执行另一部分重定向时。
paxdiablo,2009年

5
我只是意识到,最后一个示例也解决了我长期以来对于以下原因的困惑:some_program 2>&1 > /dev/null不能这样工作:some_program > /dev/null 2>&1
snapfractalpop

您对最后一个示例的评论值得用金色表示:-)我从没想过这些重定向参数是有位置的……我想知道这一点很重要。
Nils-o-mat

20

2>&1是POSIX shell构造。这是一个细分,逐个标记:


2:“ 标准错误 ”输出文件描述符。

>&复制输出文件描述符运算符(输出重定向运算符的变体>)。给定的[x]>&[y],用表示的文件描述符x是输出文件描述符的副本y

1标准输出 ”输出文件描述符。

该表达式将2>&1文件描述符复制1到location 2,因此2在执行环境中写入(“标准错误”)的任何输出都将到达最初由1(“标准输出”)描述的同一文件。


进一步说明:

文件描述符:“每个进程的唯一非负整数,用于标识打开的文件以用于文件访问。”

标准输出/错误:请参考外壳文档的“ 重定向”部分中的以下说明:

打开的文件用从零开始的十进制数字表示。可能的最大值是实现定义的;但是,所有实现应至少支持0到9(含),以供应用程序使用。这些数字称为“文件描述符”。值0、1和2具有特殊含义和常规用途,并且由某些重定向操作隐含;这些值可能会在某些情况下出现。它们分别称为标准输入,标准输出和标准误差。程序通常从标准输入获取输入,然后将输出写入标准输出。错误消息通常写在标准错误上。重定向运算符可以以一个或多个数字(不允许插入字符)开头,以指定文件描述符号。


19

2是控制台标准错误。

1是控制台标准输出。

这是标准的Unix,Windows也遵循POSIX。

例如,当您跑步时

perl test.pl 2>&1

标准错误将重定向到标准输出,因此您可以同时看到两个输出:

perl test.pl > debug.log 2>&1

执行后,您可以在debug.log中看到所有输出,包括错误。

perl test.pl 1>out.log 2>err.log

然后标准输出到out.log,标准错误到err.log。

我建议您尝试了解这些。


第二个示例是错误的:由于将订单优先级STDERR重定向到STDOUT,所以只有默认的STDOUT才会被写入debug.log(不是STDERR),请参见我的回答(第2段)!为了确保将两者都重定向到同一文件,您必须反转重定向指令:perl test.pl > debug.log 2>&1
F. Hauri 2015年

16

回答您的问题:它接受任何错误输出(通常发送到stderr)并将其写入标准输出(stdout)。

例如,当您需要分页显示所有输出时,这会很有用。有些程序喜欢将使用情况信息打印到stderr中。

为了帮助您记住

  • 1 =标准输出(程序打印正常输出)
  • 2 =标准错误(程序打印错误)

“ 2>&1”只是将发送到stderr的所有内容都指向stdout。

我还建议您阅读有关错误重定向的文章,其中详细介绍该主题。


11

从程序员的角度来看,这恰恰意味着:

dup2(1, 2);

请参见手册页

了解这2>&1是一个副本也解释了为什么...

command >file 2>&1

...与...不同

command 2>&1 >file

第一个将两个流都发送到file,而第二个将错误发送到stdout,并将普通输出发送到file


8

我发现这非常有用的,如果你是一个初学者阅读

更新:
在Linux或Unix系统中,程序将输出发送到两个位置:标准输出(stdout)和标准错误(stderr)。您可以将这些输出重定向到任何文件。

就像您执行此操作一样

ls -a > output.txt

,控制台中不会打印任何内容,所有输出(stdout)都将重定向到输出文件。

而且,如果您尝试打印不退出的任何文件的内容,则输出将是一个错误,例如,如果您打印在当前目录中不存在的test.txt,

cat test.txt > error.txt

输出将为

cat: test.txt :No such file or directory

但是error.txt文件将为空,因为我们将标准输出重定向到了不是stderr的文件。

因此,我们需要文件描述符(文件描述符只不过是代表打开的文件的正整数。您可以说描述符是文件的唯一ID)来告诉Shell我们将发送到文件的输出类型。在Unix / Linux系统中1用于stdout,2用于stderr

所以现在如果您这样做,则

ls -a 1> output.txt意味着您正在将标准输出(stdout)发送到output.txt。

如果这样做,则

cat test.txt 2> error.txt意味着您正在将标准错误(stderr)发送到error.txt。

&1用于引用文件描述符1(stdout)的值。

现在的意思2>&1是“将stderr重定向到我们将stdout重定向到的相同位置”

现在您可以执行此操作

cat maybefile.txt > output.txt 2>&1

标准输出(stdout)和标准错误(stderr)都将重定向到output.txt。

感谢Ondrej K.指出


1
仅链接答案有问题。链接可能会失效,导致答案无用。您应该始终在答案本身中包含足够的细节。
Ondrej K.

7

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

我对2>&1操作员的个人记忆是:

  • 认为&是意思'and''add'(字符是安培字符- ,不是吗?)
  • 因此它变成:'将2(stderr)重定向到1(stdout)已经/当前所在的位置,并添加两个流“

同样的助记符也可用于其他常用的重定向1>&2

  • 想一想&意义and还是add……(您对“&”号有想法,对吗?)
  • 因此它变成: '将1(stdout)重定向到2(stderr)已经/当前所在的位置,并添加两个流“

并始终记住:您必须从右到左(而不是从左到右)“从头到尾”读取重定向链。


7

重定向输入

输入重定向导致打开其名称由单词扩展引起的文件,以供在文件描述符n上读取,或者如果未指定n,则打开标准输入(文件描述符0)。

重定向输入的一般格式为:

[n]<word

重定向输出

输出重定向导致打开其名称由单词扩展产生的文件,以便在文件描述符n上进行写操作;如果未指定n,则打开标准输出(文件描述符1)。如果文件不存在,则创建该文件;如果确实存在,则将其截断为零大小。

重定向输出的一般格式为:

[n]>word

移动文件描述符

重定向运算符,

[n]<&digit-

将文件描述符数字移动到文件描述符n,或者如果未指定n,则将标准输入(文件描述符0)移动到文件描述符n。数字复制到n后关闭。

同样,重定向运算符

[n]>&digit-

将文件描述符数字移动到文件描述符n,或者如果未指定n,则将标准输出(文件描述符1)移动到文件描述符n。

参考:

man bash

键入/^REDIRECT以找到该redirection部分,并了解更多信息...

在线版本在这里:3.6重定向

PS:

很多时候,它man是学习Linux的强大工具。


6

只要/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

是简写


5

这就像将错误传递到标准输出或终端一样。

也就是说,cmd不是命令:

$cmd 2>filename
cat filename

command not found

错误将发送到文件,如下所示:

2>&1

标准错误发送到终端。


1

输入为0,标准输出为1,标准错误为2。

提示somecmd >1.txt 2>&1是正确的,而somecmd 2>&1 >1.txt完全错误是没有效果的!


1

unix_commands 2>&1

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

下面说明了过程

  • 产生错误时,会将它们写入&2标准错误流2引用的标准错误存储器地址“缓冲区” 。
  • 产生输出时,将其写入&1标准输出流1引用的标准输出存储器地址“缓冲区” 。

因此,采用unix_commands标准错误流2,并将>(错误)流重定向至标准输出内存地址&1,以便将其流式传输到终端并进行打印。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.