Bash

在執行來自 STDIN 的參數之前使 GNU Parallel 不延遲

  • April 7, 2019

沒有任何命令行選項的 GNU Parallel 允許您輕鬆地並行化其最後一個參數由一行 STDIN 確定的命令:

$ seq 3 | parallel echo
2
1
3

請注意,parallel在開始執行作業之前不要等待 STDIN 上的 EOF - 執行yes | parallel echo將立即開始列印無限多個副本y

但是,如果 STDIN 相對較短,這種行為似乎會發生變化:

$ { yes | ghead -n5; sleep 10; } | parallel echo

在這種情況下,完成前不會返回任何輸出sleep 10

這只是一個例子——實際上,我試圖從一系列連續生成的 FIFO 管道中讀取數據,在這些管道中,直到現有管道開始被消耗,FIFO 生成過程才會繼續。例如,我的命令將生成一個 STDOUT 流,如:

/var/folders/2b/1g_lwstd5770s29xrzt0bw1m0000gn/T/tmp.PFcggGR55i
/var/folders/2b/1g_lwstd5770s29xrzt0bw1m0000gn/T/tmp.UCpTBzI3J6
/var/folders/2b/1g_lwstd5770s29xrzt0bw1m0000gn/T/tmp.r2EmSLW0t9
/var/folders/2b/1g_lwstd5770s29xrzt0bw1m0000gn/T/tmp.5TRNeeZLmt

在新終端中一次一個地手動cat輸入這些文件會導致 FIFO 生成過程成功完成。但是,跑步printfifos | parallel cat不起作用。相反,parallel似乎永遠阻塞等待 STDIN 上的輸入——如果我將管道修改為printfifos | head -n4 | parallel cat,死鎖就會消失並且前四個管道被成功列印。

這種行為似乎與--jobs|-j參數有關。雖然{ yes | ghead -n5; sleep 10; } | parallel cat10 秒內沒有輸出,但添加一個-j1選項會產生四行y幾乎立即,然後等待 10 秒以等待最終的y. 不幸的是,這並不能解決我的問題——我需要先處理每個參數,然後parallel才能從讀取 STDIN 中獲取 EOF。有什麼辦法可以做到這一點?

GNU Parallel 中的一個錯誤是,它僅在為每個作業槽讀取一個作業後才開始處理。之後,它一次讀取一份作業。

在舊版本中,輸出也會因作業槽的數量而延遲。較新的版本僅延遲單個作業的輸出。

因此,如果您每秒發送一個作業,parallel -j10它將在開始之前讀取 10 個作業。在舊版本中,您必須再等待 10 秒才能看到作業 3 的輸出。

開始時限制的一種解決方法是為每個作業槽提供一個虛擬作業以並行:

true >jobqueue; tail -n+0 -f jobqueue | parallel &
seq $(parallel --number-of-threads) | parallel -N0 echo true >> jobqueue
# now add the real jobs to jobqueue

輸出要使用的解決方法--linebuffer(但這將混合來自不同作業的完整行)。

引用自:https://unix.stackexchange.com/questions/511004