2017-07-26 81 views
1
ls test.mp4 test.sh 1>/tmp/text 2>&1 
cat /tmp/text 
ls: cannot access test.sh: No such file or directory 
test.mp4 

为什么结果不是如下顺序?bash中stdout和stderr的顺序

test.mp4 
ls: cannot access test.sh: No such file or directory 

也许1>/tmp/text先执行,test.mp4定位在test.sh之前。
哪个会导致影响?

回答

3

这与bash无关。它只是反映了C标准库I/O函数缓冲输出的方式。

下面是Linux系统中man setvbuf的一个有用摘录(解释主要来自C和Posix标准,但我认为在这个摘录中很容易找到和理解)。第二段是你看到的行为的解释。

可用的三种缓冲类型是无缓冲,块缓冲和行缓冲。当输出流没有缓冲时,信息一出现就显示在目标文件或终端上;当它被块缓冲时,许多字符被保存并写成一个块;当行缓冲字符被保存直到输出换行符或从连接到终端设备(通常为stdin)的任何流读取输入时。 fflush(3)函数可以用来尽早强制阻止。 (见fclose(3)。)

通常所有文件都是块缓冲的。如果一个流引用了一个终端(正如标准输出通常那样),它是行缓冲的。标准错误流stderr默认情况下始终未缓冲。

因此,回顾一下。 stdout通常指的是终端,因此是行缓冲的,但是您已将其重定向到一个文件,因此它被块缓冲。但是,stderr始终是无缓冲的,无论它是否被重定向。

因此,任何打印到stderr的东西都会立即出现,而打印到stdout的任何内容都将保留到缓冲区填满(在Linux上通常为8kb)。

请注意,当ls检测到stdout不是终端时,它会默认设置-1标志(每行一个文件名)。否则,它会默认设置-x标志(尽可能多的文件名以适合一行)。这意味着您将在终端上看到相同的反转,而无需任何重定向:

$ ls good bad 
ls: cannot access bad: No such file or directory 
good 
2

标准输出似乎在_exit被缓存和刷新。另一方面,stderr更加紧急。我不认为bash会等到_exit才能清除它。如果它被缓冲的话。