15 题: 在shell中,“2>&1”是什么意思?

在...创建的问题 Wed, May 9, 2018 12:00 AM

在Unix shell中,如果我想将stderrstdout组合到stdout流中以进行进一步操作,我可以在命令的末尾添加以下内容:

 
2>&1

所以,如果我想在head的输出上使用g++,我可以这样做:

 
g++ lots_of_errors 2>&1 | head

所以我只能看到前几个错误。

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

有人可以打破这个并按字符解释2>&1的含义吗?

    
2019
  1. @ dbr我不认为这只是bash - 我相信它是一个bourne shell的东西;因此sh,bash,ksh,ash,dash等等。
    2009-05-03 23:49:23Z
  2. 这是描述POSIX兼容shell的重定向段落的一部分,简称POSIX shell。例如,ksh是一个POSIX shell。请参阅: pubs.opengroup.org/onlinepubs/009695399/utilities/...
    2013-04-04 02:55:51Z
  3. 此构造也适用于Windows。
    2013-10-22 13:45:03Z
  4. 通常比 2> /dev /null 更好地做2>&1 >; - )
    2013-12-08 12:11:46Z
  5. 我想如果你使用zsh,我会提到|&2>&1 |的简写。我不能说这是否适用于其他类似bourne的shell,或者它是否只是一个zsh功能。
    2013-12-17 05:20:31Z
  6. 醇>
    15答案                              15 跨度>                         

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

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

        
    2240
    2018-05-09 20:18:47Z
    1. 但是它不应该是&2>&1吗?
      2013-09-04 06:12:13Z
    2. @ Dominik:不,&只被解释为在重定向的上下文中表示“文件描述符”。写入command &2>&被解析为command &2>&1,即“在后台运行command,然后运行命令2并将其stdout重定向到其stdout”。
      2014-01-28 00:02:30Z
    3. 这里有趣的信息: mywiki.wooledge.org /BashFAQ /055
      2014-07-02 06:40:16Z
    4. 但是如何将stderr重定向到名为'& 1'的文件?
      2014-11-04 17:07:08Z
    5. @ Martin:2>'&1'
      2016-03-14 10:46:22Z
    6. 醇>
     
    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。

        
    558
    2018-07-04 20:36:11Z
    1. 这对你有意义吗,java ... 2&1 >> data.log,我看到我的一位同事这样做了吗?
      2011-07-26 19:53:29Z
    2. @Harry看起来像是一个不是bash的shell,或者是一个错字.cmd 2>&1 >> somefile.log会将stdout /stderr追加到一个文件中 - 它与上面的基本相同,用>> file追加
      2011-07-27 00:38:06Z
    3. @ dbr cmd 2>&1 >>file没有将stderr重定向到文件,但cmd >> file 2>&1确实如此。订单很重要。在第一种情况下,stderr被重定向到shell的stdout(如果以交互方式输入命令,则可能是tty),然后将stdout定向到该文件。在第二种情况下,stdout被定向到文件,然后stderr被定向到同一个地方。
      2013-07-19 13:15:25Z
    4. 我喜欢上面的答案,但它可能更清晰。 “2>& 1”将stderr重定向到stdout的目标。因此,如果您有类似“ls -l>> directoryContents 2>& 1”的内容,则结果将是名为directoryContents的文件,其中将附加工作目录的内容。如果执行中有任何错误:错误消息也会在发生时附加到directoryContents文件中。
      2015-04-17 17:36:16Z
    5. 0(or 1,2)>&0(or 1,2)是否像控制输出的选项一样? echo test >test.log 2>&1echo test 2>&1 >test.log相同吗?
      2018-06-01 12:58:13Z
    6. 醇>

    关于重定向的一些技巧

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

    1 - 覆盖或追加?

    符号>表示重定向

    •  >表示发送到整个已完成的文件,如果存在则覆盖目标(稍后参见#3 noclobber 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
    

    Nota:由于&9) 9>&2描述符会自发发生。

    附录:nota!新版 bash >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! Sam新的语法,两种方式:

     
    $ 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
    

    Nota:如果 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
    

    控制台中; - )     

    294
    2018-07-04 20:41:51Z
    1. 进一步阅读:如果你喜欢这个,你可能会赞成:重定向滥用如何导致奇怪的行为
      2013-12-10 21:14:04Z
    2. 2015-01-18 12:37:15Z
    3. 醇>

    我在重定向上找到了这篇精彩的帖子: 所有关于重定向

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

      

    $command&amp;&gt; file

    这个单行使用&>运算符将两个输出流(stdout和stderr)从命令重定向到文件。这是Bash快速将两个流重定向到同一目的地的快捷方式。

    以下是Bash重定向两个流后文件描述符表的样子:

    正如你所看到的,stdout和stderr现在都指向file。因此写入stdout和stderr的任何内容都会写入file

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

      

    $command&gt; file 2&gt;&amp; 1

    这是将两个流重定向到文件的更常见方法。第一个stdout被重定向到文件,然后stderr被复制到与stdout相同。所以两个流最终都指向file

    当Bash看到多个重定向时,它会从左到右处理它们。让我们完成这些步骤,看看会发生什么。在运行任何命令之前,Bash的文件描述符表如下所示:

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

    Next Bash看到第二个重定向2&gt;&amp; 1。我们之前没有见过这种重定向。这个复制文件描述符2是文件描述符1的副本,我们得到:

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

    但是要小心!写

      

    命令&gt;文件2&gt;&amp; 1

    与写作不同:

      

    $command 2&gt;&amp; 1&gt; file

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

    现在Bash处理从左到右的重定向。它首先看到2&gt;&amp; 1所以它将stderr复制到stdout。文件描述符表变为:

    现在Bash看到第二个重定向,>file,它将stdout重定向到文件:

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

    另请注意,在Bash中,写作

      

    $command&amp;&gt; file

    与:

    完全相同
      

    $command&gt;&amp; file

        
    85
    2018-07-05 03:43:35Z
    1. 如果“command”以数字结尾,则最后两个是不同的,因为那时它被视为>&的可选文件描述符
      2017-01-23 12:09:25Z
    2. 精彩的解释!谢谢
      2018-04-29 00:11:58Z
    3. Upvote为您提供的链接:)。那太棒了。
      2019-05-22 16:19:16Z
    4. 醇>

    数字指的是文件描述符(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工具,因此除非将其重定向到文件或其他内容,否则不会看到它。

        
    77
    2012-11-06 01:25:12Z

    该构造将标准错误流(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
    

    请注意,最后一个将指向stderroutfile2 - 它将其重定向到遇到参数时的stdoutoutfile1)和然后stdout重定向到outfile2

    这允许一些相当复杂的技巧。

        
    54
    2009-06-26 08:39:06Z
    1. 虽然最后一个例子会更加清晰:foo&gt; outfile2 2&gt; outfile1
      2009-05-04 00:15:20Z
    2. 更清楚,是的,但这不会显示重定向的“位置”性质。这个例子是设计的,因为在一行中这样做通常没有用 - 当不同的各方负责时,该方法变得非常有用他是重定向的不同部分。例如,当脚本执行一点重定向并使用另一位运行它时。
      2009-05-04 00:19:52Z
    3. 我刚刚意识到最后一个例子也解决了我为什么这样做的长期困惑:some_program 2>&1 > /dev/null不能像这样工作:some_program > /dev/null 2>&1
      2012-12-20 13:58:24Z
    4. 你对最后一个例子的评论值得用黄金字母:-)我从没想过这些重定向的论点是位置的......我认为知道这一点非常重要
      2018-04-18 09:04:34Z
    5. 醇>

    2>&1是一个POSIX shell结构。以下是按令牌分类的令牌:


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

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

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

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


    进一步解释:

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

    标准输出/错误:请参阅重定向部分:

      

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

        
    17
    2016-12-25 06:43:43Z

    2是控制台标准错误。

    1是控制台标准输出。

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

    E.g。当你运行

     
    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。

    我建议你试着理解这些。

        
    17
    2018-07-05 03:14:53Z
    1. 第二个示例错误:由于订单优先级 STDERR 被重定向到 STDOUT ,只有默认 STDOUT 将写入 debug.log (不是 STDERR ),请参阅我的回答(第2段)!要确保将两者重定向到同一文件,您必须反转重定向dir有效的:perl test.pl > debug.log 2>&1
      2015-02-10 16:04:52Z
    2. 醇>

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

    当您需要对所有输出进行分页时,这有助于例如“更多”。有些程序喜欢将使用信息打印到stderr。

    帮助你记住

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

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

    我还建议阅读这篇关于错误重定向的帖子主题详细介绍。

        
    16
    2009-05-03 23:24:58Z

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

     
    dup2(1, 2);
    

    请参阅手册页

    了解2>&1副本也解释了原因......

     
    command >file 2>&1
    

    ......与......不一样。

     
    command 2>&1 >file
    

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

        
    11
    2015-12-03 10:20:34Z

    人们总是记得 paxdiablo 关于重定向目标的当前位置的提示...... 重要。

    我对2>&1运营商的个人助记符是:

    • &视为意义'and''add'(字符是安培 - ,不是吗?)
    • 所以它变为:'将2(stderr)重定向到1(标准品)已经/当前是,添加两个流'

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

    • 想想&意思是andadd ......(你明白了&符号,是吗?)
    • 所以它变为:'将1(stdout)重定向到2(stderr)已经/当前是添加两个流'

    永远记住:你必须从右到左阅读“重定向链”(从左到右)。

        
    6
    2012-07-01 10:47:27Z

    如果您的系统上不存在/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
    

    是简写

        
    6
    2016-09-01 20:58:04Z

    这就像将错误传递给stdout或终端一样。

    也就是说,cmd不是命令:

     
    $cmd 2>filename
    cat filename
    
    command not found
    

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

     
    2>&1
    

    标准错误发送到终端。

        
    5
    2018-07-05 03:17:17Z
    1. 该命令行示例不是清除河你能详细说明吗?
      2018-07-05 03:20:13Z
    2. 醇>
      

    重定向输入

         

    重定向输入会导致名称为的文件   从扩展单词的结果打开文件阅读   描述符n,或标准输入(文件描述符0),如果n是   未指定。

         

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

     
    [n]<word
    
         

    重定向输出

         

    输出的重定向导致文件的输出   名称的结果来自要打开以供写作的单词的扩展   文件描述符n,或标准输出(文件描述符1),如果n   未指定。如果文件不存在则创建;如果它   确实存在它被截断为零大小。

         

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

     
    [n]>word
    
         

    移动文件描述符

         

    重定向运算符

     
    [n]<&digit-
    
         

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

         

    类似地,重定向运算符

     
    [n]>&digit-
    
         

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

    价:

     
    man bash
    

    输入/^REDIRECT以找到redirection部分,并了解更多...

    在线版本在此处: 3.6重定向一>

    PS:

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

        
    4
    2018-07-05 03:25:15Z

    0表示输入,1表示stdout,2表示stderr。

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

        
    1
    2016-07-25 09:46:19Z
来源放置 这里