2015-06-22 34 views
1

我想從的拷貝stdout到的一個日誌文件,這意味着我不想調用帶有輸出的腳本來管理髮球,我想腳本本身來處理它。我已經成功地使用this答案做到這一點,使用下面的代碼:從bash腳本本身拷貝* unbuffered * stdout到文件

#!/bin/bash 
exec > >(sed "s/^/[${1}] /" | tee -a myscript.log) 
exec 2>&1 

# <rest of script> 
echo "hello" 
sleep 10 
echo "world" 

這工作,但被緩衝輸出的缺點,直到腳本完成,如在鏈接的答案了討論。在上面的例子中,只有在10秒後,「hello」和「world」纔會出現在日誌中。

我知道stdbuf命令,如果用

stdbuf -oL ./myscript.sh 

運行腳本,然後標準輸出確實是連續打印既文件和終端。 但是,我希望在腳本中處理這個問題。有什麼辦法可以將這兩種解決方案結合起來?我寧願不求助於一個包裝腳本,它簡單地調用由「stdbuf -oL」包圍的原始腳本。

回答

0

您可以使用一種變通方法,使腳本執行本身stdbuf,如果一個特殊的參數存在:

#!/bin/bash 

if [[ "$1" != __BUFFERED__ ]]; then 
    prog="$0" 
    stdbuf -oL "$prog" __BUFFERED__ "[email protected]" 
else 
    shift #discard __BUFFERED__ 

    exec > >(sed "s/^/[${1}] /" | tee -a myscript.log) 
    exec 2>&1 

    # <rest of script> 
    echo "hello" 
    sleep 1 
    echo "world" 
fi 

這將主要工作:

  • 如果您運行./test腳本,它顯示無緩衝[] hello\n[] world
  • 如果您使用./test 123 456運行腳本,則會顯示您想要的[123] hello\n[123] world
  • 但是,如果您使用bash test - $0設置爲test而不是您的腳本,它將無法正常工作。解決這個問題不在這個問題的範圍之內。
+0

感謝。這些限制確實沒問題。這可能不是最乾淨的解決方案:-)但我會嘗試。 – JHH

0

在你的第一個解決方案的延遲是由sed引起的,而不是由tee。試試這個:

#!/bin/bash 
exec 6>&1 2>&1>&>(tee -a myscript.log) 

要 「撤銷」 tee效果:

exec 1>&6 2>&6 6>&- 
+0

謝謝。你確定關於tee vs sed嗎?很確定沒有sed發生了同樣的事情,但我會仔細檢查。另外,你是否介意解釋你的建議,6是什麼? – JHH

+0

我遇到了[類似的](http://stackoverflow.com/questions/30786082/convert-expect-output-from-dos-to-unix-style-in-realtime)問題(首先沒有完全連接到你的視線),其中我試圖通過將其stdout管道輸出到sed/perl/tr/dos2unix/etc並同時使用「tee」來複制某個進程的輸出來「dos2unix」。兩個啓用時我都無法擺脫惱人的延遲/緩衝效果。我最終決定'只*'*並在稍後執行'dos2unix'。更多信息將stdout/stderr重定向到fd6 [here](http://www.tldp.org/LDP/abs/html/x17974.html) –