Bash
避免在 bash 腳本中對命令組(大括號)進行輸出緩衝
我有一個 bash 腳本,其中包含花括號中的一組命令
{ ... }
。該組包含一些初始echo
命令,然後是一個循環。在每次迭代中,循環都會執行各種慢速命令(基本上帶有curl
一些額外的解析)。每次迭代都很慢(由於網路互動),但它會列印一行(python 程式碼);據我所知,命令本身不應該有緩衝問題,因為它們會終止工作並離開。整個命令組通過管道傳輸到
python -u
(我也嘗試使用tail -f
以進行檢查),顯然整個循環在python -u
or讀取任何內容之前執行tail -f
。我知道如何使用各種工具(如可能)取消緩衝(如果可能)一個
stdbuf
命令,但我認為它在這裡沒有幫助,因為看起來問題來自命令分組而不是來自這樣或這樣的命令。有什麼提示嗎?
(未來的讀者請注意:這裡的憤怒語氣不是針對問題,而是針對我在嘗試回答問題時所犯的錯誤以及它們需要進行的多次編輯。)
哦,看在憐憫的份上。問題出在
tail -f
. 這工作得很好:#!/bin/bash printf 'hi\n' { for i in 1 2 3 4; do sleep 0.5 /bin/echo $i done; } | cat printf 'bye\n'
這不是管道,也不是組。是
tail
。就像,追逐我們自己的尾巴!所以,
tail -f
失敗是因為它由於某種原因沒有立即輸出。不知道為什麼python -u
會失敗,但我認為腳本中沒有任何內容。也許嘗試unbuffer
一下。cat
至少嘗試使用您的腳本,並驗證它在這種情況下是無緩衝的。先前失敗的嘗試故意留在這裡,以便未來的讀者可以理解這些評論。
此腳本展示了您遇到的相同類型的緩衝問題:
#!/bin/bash printf 'hi\n' { for i in 1 2 3 4; do sleep 0.5 printf '%s\n' $i done; } | tail -f printf 'bye\n'
這個沒有。組內的輸出被重定向到 stderr,然後整個組的 stderr 通過管道傳送到命令。因為它是標準錯誤,所以它是無緩衝的。
#!/bin/bash printf 'hi\n' { for i in 1 2 3 4; do sleep 0.5 printf '%s\n' $i 1>&2 done; } |& tail -f printf 'bye\n'
改編自王洪欽對這個問題的回答。困難在於找到一種用大括號而不是顯式命令來解除管道緩衝的方法。不得不擺弄一段時間才能使重定向正常工作。