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
为什么结果不是以下顺序?
test.mp4
ls: cannot access test.sh: No such file or directory
首先执行1>/tmp/text
,test.mp4在test.sh之前找到
哪个效果如何呢?
答案 0 :(得分:4)
这与bash无关。它只是反映了C标准库I / O函数缓冲输出的方式。
这里是man setvbuf
在Linux系统上的有用摘录(解释主要来自C和Posix标准,但我认为在此摘录中很容易找到并理解) 。第二段是对你所看到的行为的解释。
可用的三种缓冲类型是无缓冲,块缓冲和行缓冲。当输出流未缓冲时,一旦写入,信息就会出现在目标文件或终端上;当它被块缓冲时,许多字符被保存起来并写成块;当它是行缓冲时,字符被保存,直到输出换行符或从连接到终端设备的任何流中读取输入(通常是stdin)。函数fflush(3)可用于提前阻止块。 (见fclose(3)。)
通常所有文件都是块缓冲的。如果流引用终端(正如stdout通常那样),则它是行缓冲的。默认情况下,标准错误流stderr始终是无缓冲的。
所以,回顾一下。 stdout
通常是指终端,因此是行缓冲的,但您已将其重定向到文件,因此它是块缓冲的。但是,stderr
始终是无缓冲的,无论它是否已被重定向。
因此,打印到stderr
的任何内容都会立即显示,而打印到stdout
的任何内容都将被保留,直到缓冲区填满(在Linux上,通常为8kb)。
请注意,当ls
检测到stdout
不是终端时,它会默认设置-1
标记(每行一个文件名)。否则,它将默认设置-x
标志(与一行中适合的文件名一样多)。这意味着您将在终端上看到相同的反转而没有任何重定向:
$ ls good bad
ls: cannot access bad: No such file or directory
good
答案 1 :(得分:2)
stdout似乎在_exit上进行了缓冲和刷新。 另一方面,斯特德尔则更为紧迫。我不认为bash会等到_exit才能刷新它。如果它被缓冲了。