2>&1> output.log和2>&1 |之间的区别 三通output.log


35

我想知道以下两个命令之间的区别

2>&1 > output.log 

2>&1 | tee output.log

我看到一位同事使用第二个选项进行重定向。我知道2>&1是什么,我唯一的问题是在可以使用简单重定向“>”运算符的地方使用tee的目的是什么?

Answers:


11

分别查看两个命令:

utility 2>&1 >output.log 

在这里,由于重定向是以从左到右的方式处理的,因此标准错误流将首先被重定向到标准输出流去往的任何地方(可能到控制台),然后标准输出流将被重定向到文件。标准错误流不会重定向到该文件。

可见的效果是,您可以在屏幕上获得标准错误产生的结果以及文件中标准输出产生的结果。

utility 2>&1 | tee output.log

在这里,您将标准错误重定向到与标准输出流相同的位置。这意味着两个流都将tee作为单个混合的输出流通过管道传输到实用程序,并且该标准输出数据将通过保存到给定文件tee。数据将另外tee在控制台中复制(这是这样tee做的,它复制数据流)。

使用哪种方法取决于您想要实现的目标。

请注意,您将无法使用just来重现第二个管道的效果>(如中所示utility >output.log 2>&1,这将在文件中保存标准输出和错误)。您将需要使用tee来获取控制台以及输出文件中的数据。


附加条款:

第一个命令的可见效果,

utility 2>&1 >output.log 

将与

utility >output.log

即,标准输出进入文件,标准错误进入控制台。

如果在上述每个命令的末尾添加了进一步的处理步骤,则会有很大的不同:

utility 2>&1 >output.log | more_stuff

utility >output.log      | more_stuff

在第一个管道中,more_stuff将从utility其标准输入数据中获取最初的标准错误流,而在第二个管道中,由于只有通过管道发送的最终标准输出流,more_stuff该管道的任何部分都将一无所获读取其标准输入。


使用命令“” utility 2>&1 | tee output.log,您是说由于1被定向到tee,2也被定向。由于tee复制了流,所以输出既显示在控制台上又写入了文件?因此,utility 2>&1 > output.log和之间的区别utility 2>&1 | tee output.logtee因为它复制了视频流,对吗?
动机

utility 2>&1 > output.log | more_stuffutility >ouput.log| 的例子 more_stuff , is the difference that more_stuff`是否将标准错误输出到控制台作为输入more_stuff?由于在第二个示例中,没有任何输出到控制台,因此基本上没有输入到more_stuff?。如果是的话,这是不清楚的,因为上一段您会注意到标准输出进入文件,而标准错误进入控制台。
推动下

@Motivated您的第一句话对我来说似乎是正确的。至于第二条注释:在第一个命令中,more_stuff将接收utility最初发送到其错误流的内容(但将其重定向到标准输出)。不是因为它more_stuff不出现在控制台上,而是因为它将进入标准输出流。在第二个命令中,什么都没more_stuff收到,因为管道的左侧没有标准输出。来自的错误流仍将在第二个命令中最终出现在控制台上。utility
库萨兰达

谢谢。您的意思是因为utility > output.log | more_stuff从标准错误的角度来看,该命令不会在标准输出流中导致输出?
动机

@Motivated由于左侧在标准输出上不产生任何内容(已重定向),因此不会通过管道发送任何数据。
库萨兰达

24

编者注

请务必阅读本答案的评论 - derobert


原始答案

2>&1 >output.log意味着首先开始将所有文件句柄2的东西(标准错误)发送到文件句柄1(标准输出),然后将其发送到文件output.log。换句话说,将标准错误和标准输出发送到日志文件。

2>&1 | tee output.log2>&1位相同,它将标准输出和标准误差组合到标准输出流上。它然后通过管道穿过tee这将它的标准输入发送到其标准输出(如程序cat),并给该文件。因此,它将两个流(错误和输出)结合在一起,然后将其输出到终端和文件。

底线是,所述第一发送stderr/ stdout到该文件,而第二个将其发送到两个文件和标准输出(这是可能的终端,除非你已重定向标准输出的另一构建体内部)。

我提到最后一种可能性,因为您可以拥有以下内容:

(echo hello | tee xyzzy.txt) >plugh.txt

终端上什么都没有结束。


13
-1您拥有语法权利,但没有语义。运行cat /doesnotexist 2>&1 >output.txt-您将看到cat: /doesnotexist: No such file or directory显示在终端上,并且output.txt是一个空文件。优先顺序和结束顺序在起作用:(2>&1将fd1 从当前 fd1 复制到fd2 ),然后>output.txt(将fd1重定向到output.txt,而不更改其他任何内容)。2>&1 |不同的原因是由于优先顺序:|before >
Arcege 2011年

5
从根本上说,这个答案在每个方面都是错误的。下面的许多答案都比较好,但是我认为Kusalananda的答案是最清楚的。
迈克尔·荷马

2
@ user14408:如果您曾经在Unix和Linux上注册过帐户并要求得到此答案,请在处理完评论后随时删除我的编辑说明。
derobert

8

第一个命令将执行另一项任务:

2>&1 > output.log 

旧的STDOUT将保存(复制)到STDERR中,然后STDOUT将被重定向到文件。

因此,stdout将进入文件,而stderr将进入控制台。

而在

 2>&1 | tee output.log

两个流都将重定向到tee。Tee会将任何输入复制到其标准输出(在您的情况下为控制台)并复制到文件(output.log)。

第一种形式是:

    > output.log  2>&1

这会将STDOUT和STDERR都重定向到该文件。


4

前者仅输出到文件。第二个输出到文件屏幕。


4

原因2>&1 | tee是能够将stdout和stderr都捕获到日志文件中,并同时在屏幕上查看它。也可以执行此操作>output.txt 2>&1 & tail -f,但是您不知道后台命令何时终止-是程序终止还是没有输出运行。2>&1 | tee对于程序员来说,这是一个常见的习惯用法。


您是否要说例如2>&1> file.txt不会同时将stdout和stderr捕获到file.txt?
动机

0

我们先来看一些示例代码:

#include <stdio.h>
main() 
{
// message 1, on stdout (using  printf)
printf("%s",          "message 1, on stdout (using  printf)\n");

// message 2, on stdout (using fprintf)
fprintf(stdout, "%s", "message 2, on stdout (using fprintf)\n");

// message 3, on stderr (using fprintf)
fprintf(stderr, "%s", "message 3, on stderr (using fprintf)\n");
}

让我们比较结果:
./helloerror
+文件:无消息;控制台:消息1,2,3;

./helloerror >error.txt
+文件:消息1,2; 控制台:消息3;

./helloerror 2>&1 >error.txt
+文件:消息1,2;控制台:消息3;
+与./helloerror> error.txt相同

./helloerror >error.txt 2>&1
+文件:消息3,1,2; 控制台:无消息;
+注意顺序3是第一个,然后是1,然后是2

./helloerror | tee error.txt 2>&1
+文件:消息1,2;控制台:消息3,1,2;
+注意顺序3是第一个,然后是1,然后是2

./helloerror 2>&1 | tee error.txt
+文件:消息3,1,2; 控制台:消息3,1,2;

使用方法:
./helloerror >error.txt 2>&1
->如果要在文件中保存所有(stdout + stderr)消息,但不固定在控制台上

./helloerror 2>&1 | tee error.txt
->如果希望将所有(stdout + stderr)消息记录在文件中并打印在控制台上


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.