2014-09-24 68 views
4

異步消耗管我有這樣使用bash

data_generator_that_never_guits | while read data 
do 
an_expensive_process_with data 
done 

第一處理bash腳本連續地產生,其需要被處理,因爲它們變得可用事件(以不規則的間隔)。這個腳本的一個問題是讀取消耗一行輸出;由於處理非常昂貴,我希望它能夠消耗當前可用的所有數據。另一方面,如果有新的數據可用,處理必須立即開始。在簡單地說,我想要做這樣的事情

data_generator_that_never_guits | while read_all_available data 
do 
an_expensive_process_with data 
done 

在命令read_all_available將等待如果沒有數據可用於消費或全部現有數據複製到變量。如果數據不包含全行,那就太好了。基本上,我正在尋找一種讀取模擬,它將讀取整個管道緩衝區,而不是從管道讀取一行。

爲了您的好奇,我有一個構建腳本需要觸發重建源文件更改的問題的背景。我想避免經常觸發重建。請不要建議我使用grunt,gulp或其他可用的構建系統,它們不適合我的目的。

謝謝!

回答

1

我想我已經找到了解決方案後,我得到了更好的見解如何subhells工作。這個腳本用來做什麼,我需要:

data_generator_that_never_guits | while true 
do 
# wait until next element becomes available 
read LINE 
# consume any remaining elements — a small timeout ensures that 
# rapidly fired events are batched together 
while read -t 1 LINE; do true; done 
# the data buffer is empty, launch the process 
an_expensive_process 
done 

這將有可能收集所有的讀線單批,但我真的不關心在這一點上他們的內容,所以我沒有懶得搞清楚的那部分:)

添加於2014年9月25日

下面是一個最終的子程序,在情況下,它可能是有人1天有用:

flushpipe() { 
# wait until the next line becomes available 
read -d "" buffer 
# consume any remaining elements — a small timeout ensures that 
    # rapidly fired events are batched together 
while read -d "" -t 1 line; do buffer="$buffer\n$line"; done 
echo $buffer 
} 

使用是這樣的:

data_generator_that_never_guits | while true 
do 
# wait until data becomes available 
data=$(flushpipe) 
# the data buffer is empty, launch the process 
an_expensive_process_with data 
done 
0

類似read -N 4096 -t 1可能會訣竅,或者可能read -t 0與額外的邏輯。有關詳細信息,請參閱Bash參考手冊。否則,你可能不得不從Bash移動到例如Perl的。

+0

謝謝你的回答,塞巴斯蒂安。我不太確定這是如何在我的情況下工作。我的印象是,如果沒有輸入,讀取會失敗,終止循環?無論如何,我想等待輸入(無限期地如果必須)。只是我想在數據出現後清除整個管道。我已經有了一個運行良好的Python版本,但它過長而且繁瑣,因爲它必須執行一堆shell命令。 – MrMobster 2014-09-24 15:55:54