# 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
$ 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 --->
当 set -o noclobber 指示bash到 not 覆盖任何现有文件时, >| 语法允许您通过此限制:
$ 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 - 最后的伎俩......
为了从给定命令重定向 both 输出,我们看到正确的语法可能是:
$ 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
4 b-现在,我会让你考虑一下:
$ 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/
15 回答
将stdout重定向到
afile.txt
. 这和做的一样要重定向stderr,您可以:
>&
是将流重定向到另一个文件描述符的语法 - 0是stdin,1是stdout,2是stderr .您可以通过执行以下操作将stdout重定向到stderr:
或相反亦然:
所以,简而言之......
2>
将stderr重定向到(未指定的)文件,追加&1
将stderr重定向到stdout .数字指的是文件描述符(fd) .
零是
stdin
一个是
stdout
两个是
stderr
2>&1
将fd 2重定向到1 .如果程序使用它,这适用于任意数量的文件描述符 .
如果忘了它们,你可以看
/usr/include/unistd.h
:这就是说我编写了使用非标准文件描述符进行自定义日志记录的C工具,因此除非将其重定向到文件或其他内容,否则不会看到它 .
该构造将标准错误流(
stderr
)发送到标准输出的当前位置(stdout
) - 这个货币问题似乎被其他答案忽略了 .您可以使用此方法将任何输出句柄重定向到另一个输出句柄,但它最常用于将
stdout
和stderr
流引导到单个流中进行处理 .一些例子是:
请注意,最后一个不会将
stderr
指向outfile2
- 它会将其重定向到遇到参数时的stdout
(outfile1
),然后将stdout
重定向到outfile2
.这允许一些非常复杂的技巧 .
回答你的问题:它需要任何错误输出(通常发送到stderr)并将其写入标准输出(stdout) .
当您需要对所有输出进行分页时,这有助于例如“更多” . 有些程序喜欢将使用信息打印到stderr中 .
帮助你记住
1 =标准输出(程序打印正常输出)
2 =标准错误(程序打印错误)
“2>&1”只是将发送到stderr的所有内容指向stdout .
我还建议阅读this post on error redirecting,其中详细介绍了该主题 .
参考:
键入
/^REDIRECT
以找到redirection
部分,并了解更多...在线版本在这里:3.6 Redirections
PS:
很多时候,
man
是学习Linux的强大工具 .2>&1
是POSIX shell构造 . 以下是按令牌分类的令牌:2
:“ Standard error ”输出文件描述符 .>&
:Duplicate an Output File Descriptor运算符(Output Redirection运算符>
的变体) . 给定[x]>&[y]
,x
表示的文件描述符将成为输出文件描述符y
的副本 .1
“ Standard output ”输出文件描述符 .表达式
2>&1
将文件描述符1
复制到位置2
,因此在执行环境中写入2
("standard error")的任何输出都将转到最初由1
("standard output")描述的同一文件 .进一步说明:
File Descriptor:"A per-process unique, non-negative integer used to identify an open file for the purpose of file access."
Standard output/error :请参阅shell文档的Redirection部分中的以下注释:
这就像将错误传递给stdout或终端一样 .
也就是说,
cmd
不是命令:错误发送到文件,如下所示:
标准错误发送到终端 .
关于重定向的一些技巧
关于此的一些语法特殊性可能具有重要的行为 . 有一些关于重定向的小样本,
STDERR
,STDOUT
和参数 ordering .1 - 覆盖或追加?
符号
>
表示重定向 .>
表示发送到整个已完成的文件,如果存在则覆盖目标(稍后请参阅#71586_ bash功能#3) .>>
如果存在,则另外发送将附加到目标 .在任何情况下,如果文件不存在,将创建该文件 .
2 - shell命令行依赖于订单!!
为了测试它,我们需要一个简单的命令,它将在两个输出上发送一些东西:
(当然,期待您没有名为
/tnt
的目录;) . 好吧,我们拥有它!所以,让我们看看:
最后一个命令行将
STDERR
转储到控制台,它似乎不是预期的行为......但......如果你想对一个输出,另一个或两个输出进行一些后置过滤:
请注意,此段落中的最后一个命令行与上一段中的完全相同,我写的内容似乎不是预期的行为(因此,这甚至可能是预期的行为) .
嗯,有一些关于重定向的小技巧,对于 doing different operation on both outputs :
Nota:
&9
描述符会因为) 9>&2
而自发发生 .Addendum: nota! 使用bash(
>4.0
)的新版本,有一个新功能和更性感的语法来执行此类操作:最后对于这样的级联输出格式:
Addendum: nota! 相同的新语法,两种方式:
STDOUT
通过一个特定的过滤器,STDERR
到另一个,最后两个输出合并通过第三个命令过滤器 .3 - 关于noclobber选项和> |的一个词句法
那是关于 overwriting :
当
set -o noclobber
指示bash到 not 覆盖任何现有文件时,>|
语法允许您通过此限制:每次都会覆盖该文件,现在好了:
通过
>|
:取消设置此选项和/或询问是否已设置 .
4 - 最后的伎俩......
为了从给定命令重定向 both 输出,我们看到正确的语法可能是:
对于这种特殊情况,有一种快捷语法:
&>
...或>&
注意:如果 2>&1 存在, 1>&2 也是正确的语法:
4 b-现在,我会让你考虑一下:
4 c-如果您对更多信息感兴趣
您可以通过点击阅读精细手册:
在一个bash控制台;-)
文件描述符1是标准输出(
stdout
) .文件描述符2是标准错误(
stderr
) .这是记住这个结构的一种方法(尽管它并不完全准确):首先,
2>1
可能看起来像是将stderr
重定向到stdout
的好方法 . 但是,它实际上将被解释为“将stderr
重定向到名为1
的文件” .&
表示后面是文件描述符而不是文件名 . 所以构造变成:2>&1
.2是控制台标准错误 .
1是控制台标准输出 .
这是标准的Unix,Windows也遵循POSIX .
例如 . 当你跑步
标准错误被重定向到标准输出,因此您可以同时看到两个输出:
执行后,您可以在debug.log中查看所有输出,包括错误 .
然后标准输出转到out.log,标准错误转到err.log .
我建议你试着理解这些 .
人们,永远记得paxdiablo关于重定向目标 current 位置的暗示......重要的是 is .
我对
2>&1
运算符的个人助记符是这样的:将
&
视为含义'and'
或'add'
(该字符为ampers- and ,不是吗?)因此它变成:'重定向
2
(stderr)到1
(标准输出)已经/当前是 add 两个流' .同样的助记符也适用于其他常用的重定向,
1>&2
:想到
&
意思是and
或add
......(你明白了&符号,是吗?)所以它变成:'重定向
1
(标准输出)到2
(stderr)已经/当前是 add 两个流' .永远记住:你必须从右到左阅读重定向链'from the end'( not 从左到右) .
我在重定向上找到了这篇精彩的帖子:All about redirections
Redirect both standard output and standard error to a file
这个单行使用
&>
运算符将两个输出流(stdout和stderr)从命令重定向到文件 . 这是Bash快速将两个流重定向到同一目的地的快捷方式 .以下是Bash重定向两个流后文件描述符表的样子:
如您所见,stdout和stderr现在都指向
file
. 因此写入stdout和stderr的任何内容都会被写入file
.有两种方法可以将两个流重定向到同一目标 . 您可以一个接一个地重定向每个流:
这是将两个流重定向到文件的更常见方法 . 第一个stdout被重定向到文件,然后stderr被复制到与stdout相同 . 所以两个流最终都指向
file
.当Bash看到几个重定向时,它会从左到右处理它们 . 让我们完成这些步骤,看看会发生什么 . 在运行任何命令之前,Bash的文件描述符表如下所示:
现在Bash处理第一个重定向>文件 . 我们之前已经看过这个,它使stdout指向文件:
下一个Bash看到第二个重定向2>&1 . 我们之前没有见过这种重定向 . 这个复制文件描述符2是文件描述符1的副本,我们得到:
两个流都已重定向到文件 .
不过要小心!写作
与写作不同:
重定向的顺序在Bash中很重要!此命令仅将标准输出重定向到文件 . stderr仍会打印到终端 . 要理解为什么会发生这种情况,让我们再次讨论这些步骤 . 所以在运行命令之前,文件描述符表如下所示:
现在Bash处理从左到右的重定向 . 它首先看到2>&1所以它将stderr复制到stdout . 文件描述符表变为:
现在Bash看到第二个重定向
>file
,它将stdout重定向到file:你看到这里发生了什么? Stdout现在指向文件,但是stderr仍然指向终端!写入stderr的所有内容仍会打印到屏幕上!所以要非常非常小心重定向的顺序!
还要注意在Bash中写作
与以下内容完全相同:
0表示输入,1表示stdout,2表示stderr .
One Tip :
somecmd >1.txt 2>&1
是正确的,而somecmd 2>&1 >1.txt
完全 wrong 没有效果!如果您的系统上不存在
/foo
且/tmp
确实...将打印
/tmp
的内容并打印/foo
的错误消息将
/tmp
的内容发送到/dev/null
并打印/foo
的错误消息会做同样的事情(注意 1 )
将打印
/tmp
的内容并将错误消息发送到/dev/null
将发送列表以及错误消息发送到
/dev/null
是简写
从程序员的角度来看,它恰恰意味着:
见man page .
了解
2>&1
是一个副本也解释了为什么............和...不一样
第一个将两个流发送到
file
,而第二个将发送错误到stdout
,普通输出发送到file
.