为什么将输出重定向到2>&1和1>&2?


36

我遇到了几个使用2>&1和的命令1>&2,但是我完全无法理解使用它的目的以及何时使用它。

我的理解

我知道这1代表标准输出,2代表标准错误。我了解2>&12to 的输出1与反之亦然。

我不明白

  1. 我什么时候应该使用它?
  2. 它有什么作用?

Answers:


39

有时您想将stdout stderr 都重定向到同一位置,这>&是使用时–它将一个文件描述符指向另一个文件描述符。


例如,如果您要将stdout和stderr都写到同一个文件(它是/dev/nulloutput.txt)中,则可以使用

app 1>/dev/null 2>/dev/null

或者,您可以将一个文件描述符重定向到文件,将另一个文件描述符重定向到第一个文件描述符:

app 1>/dev/null 2>&1

app 2>/dev/null 1>&2

在第一个示例中,将2>&1文件描述符#2指向#1已经指向的位置。第二个示例实现了相同的功能,只是从stderr开始。

作为另一个示例,在某些情况下,stdout(文件描述符#1)已经指向所需的位置,但是您不能按名称引用它(它可能与管道,套接字等相关联)。在使用进程扩展(the ` `$( )operator)时通常会发生这种情况,通常只捕获stdout,但您可能希望在其中包含stderr。在这种情况下,您还可以>&将stderr指向stdout:

out=$(app 2>&1)

另一个常见的示例是寻呼机或grep或类似的实用程序,因为管道|通常仅在stdout上工作,因此在使用管道之前,您需要将stderr重定向到stdout:

app 2>&1 | grep hello

如何知道哪些的2>&1或者1>&2是正确的?在已经建立的文件描述符去的权利>&,并且希望重定向文件描述符转到左边。(2>&1表示“将文件描述符#2指向文件描述符#1”。)


有些外壳程序具有用于常见重定向的快捷方式。这是Bash的示例:

  • 1> 可以缩短为 >

  • 1>foo 2>&1>&foo&>foo

  • 2>&1 | program|& program


我不知道这样做app 1>/dev/null 2>&1意味着2>&1会指向1已经重定向到的文件。我认为我可以轻松地做到app > /dev/null &>吗?
PeanutsMonkey 2012年

我很难理解the already set up fd goes to the right of >&, and the fd you want to redirect goes to the left。您已经设置的文件描述符是什么意思?这意味着什么?
PeanutsMonkey 2012年


抱歉,除非您打算教我指导,否则我不会遵循您之前所说的声明。
PeanutsMonkey 2012年

1
使每个文件描述符一次从左到右重定向,然后按该顺序应用这些规则。如果您首先将stdout 定向到文件,然后将stderr重定向到stdout我们现在指向的位置,则stderr和stdout将转到同一文件。如果你身边交换这两个重定向,那么你会得到不同的结果(stderr重定向到标准输出是怎么回事,现在,然后移动到标准输出点到另一个文件中,而标准错误继续它指向了)。
杰森

2

您需要的一种情况是要strace在寻呼机中显示输出。strace将其输出打印为标准错误,并且管道通常将标准输出连接至标准输入,因此您必须使用重定向:

strace -p $pid 2>&1 | less

你是什么意思pipes generally connect standard output to standard input
PeanutsMonkey,2012年

2
我的意思是管道(|)接受第一个命令的标准输出,并将其连接到第二个命令的标准输入。
jpalecek 2012年

2

有时您想将stdout1)和stderr2)都重定向到同一位置(/dev/null例如,)。实现此目的的一种方法是:

$ program 1>/dev/null 2>/dev/null

但大多数人缩短这个通过重定向stderrstdout2>&1

$ program 1>/dev/null 2>&1

甚至更短的版本是:

$ program >&- 2>&-

1

2:用于当您同时具有来自标准错误和标准输出的输出,并且希望将它们组成一个字符串时。

1:要同时处理标准错误和标准输出的输出时。


你指的是什么意思?我的理解是任何重定向到的>2都发送到/ dev / null。还是我完全理解错了?
PeanutsMonkey,2012年

那是不对的。通过操纵,我的意思是将其传递给grep或类似的东西。请参阅此处的示例。
soandos 2012年

0

我用它来开始一个独立的工作:

someProgram 2>&1 >& my.log &

然后我可以注销,并且someProgram仍将运行。该功能由GNU Screen,tmux和其他一些程序提供-但是在这里它是在没有外部依赖的情况下实现的。


1
只要没有SIGHUP发送到该程序,它就起作用。更好地使用nohupdisown在这种情况下。
slhck

@slhck:好的。但是,如果我不发送SIGHUP到程序中-没人会吧?
Adobe

否,控制终端将通过SIGHUP警告注销过程。实际上,例如,如果您通过SSH运行远程shell并退出,则您的进程也会终止。
slhck

@slhck:可能不正确:我使用了几年-我注销了ssh,该过程仍在运行。
Adobe

我将不得不对此进行更详细的查找,但是仅在所有情况下将程序置于后台并不适合我,而且它甚至在我的本地计算机上也无法正常工作。看起来Zsh和Bash在这里的行为也不同。
slhck

0

想象有一个目录try,其中包含以下三个文件:file file1 and file2.

现在运行以下命令:

cat file file1 file2 file3

前三个文件打开,但是cat在打开第四个文件时抛出错误,因为它不存在。

现在运行:

cat file file1 file2 file3 1>outfile 2>&1

你不会看到屏幕上的任何输出:首先1>outfile将重定向命令的输出outfile,然后它会重定向(2>&1)引发的错误,而试图打开file3outfile

1>&2 工作原理相似,并将错误流重定向到标准输出。

希望这可以帮助!


0

替代方案:终端命令将输出显示到另一个终端

tty在每个终端中使用命令来标识它们:

$ tty
/dev/pts/0

$ tty
/dev/pts/1

假设这些TTY,要将第一个的stdout重定向到第二个,在第一个终端中运行:

exec 1>/dev/pts/1

注意:现在每个命令输出将在pts / 1上显示

恢复默认行为标准输出pts / 0:

exec 1>/dev/pts/0

观看此视频进行演示。


0

将stderr重定向到stdout的情况已经在这里讨论过(例如,使用它来过滤(grep)错误消息)。

另一种情况是将stdout重定向到stderr。一个常见的用例(至少对我而言)是将打印有“ echo”(在我的shellscript中)的警告/错误消息发送到stderr(以便它们可以更轻松地引起用户的注意)。

例如,

echo "file \"${file\" does not exist..." 1>&2
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.