Bash
命令替換中的阻塞/非阻塞管道/重定向
我在 bash 中觀察到以下行為:
{ echo 'foo' ; sleep 10 ; }
-> 標準輸出“foo”立即出現,10 秒後命令完成(如預期)
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo')
-> 標準輸出“foo”立即出現,10 秒後命令完成(如預期)
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo' | grep 'oo')
-> 標準輸出“foo”在 10 秒後出現
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo' >&2)
-> 10 秒後出現標準錯誤“foo”
為什麼命令替換中帶有單個 grep 的命令行會立即輸出其結果,而帶有管道和重定向的變體要等到睡眠結束?
你不需要那麼花哨;你可以觀察到同樣的效果
{ echo 'foo' ; sleep 10 ; } | grep oo | grep oo
或者
{ echo 'foo' ; sleep 10 ; } | grep oo | cat
或者
- 打開兩個終端。轉到兩者中的相同目錄(例如,您的主目錄或
/tmp
)。- 在一個,做
{ echo 'foo' ; sleep 10 ; } | grep oo > foo.out
。- 另一方面,
ls -ld foo.out
反复做。您將看到該
foo.out
文件立即出現,但大小為 0 十秒鐘,之後變為 4 個字節長。簡單地說:
grep
測試它的(標準)輸出是否是終端。如果是,它會盡快寫入輸出,因為它有輸出要寫入。如果不是,它會緩衝其輸出,並一次寫入N 個字節,其中N 通常為 512,但在某些實現中可能會有所不同。