Shell-Script
當兩個子外殼寫入標準輸出時排序輸出
我有以下形式的命令
input | tee >(subshell) | mainshell
subshell 和 mainshell 都寫入標準輸出。所以他們的輸出是不同步的。例如
echo "Hello\nWorld" | tee >(grep -o ell | tr 'a-z' 'A-Z') | grep orld | sed 's/orl/ORL/g'
上面的命令列印
ELL WORLd
有時和
WORLd ELL
其他時間。
有沒有一種簡單的方法來確保它們符合預期的順序,而不必使用臨時文件/命名的 fifos?可能打開一些文件描述符重定向會有所幫助嗎?
更新:
按順序,我的意思是輸出主外殼,然後是子外殼(反之亦然)。如果它以一種或另一種方式是確定性的,我可以根據我的需要交換它們。
同樣可以通過命名 fifo 來實現,如下所示
mkfifo f1 f2 echo "Hello\nWorld" | tee >(grep -o ell | tr 'a-z' 'A-Z' > f1) | grep orld | sed 's/orl/ORL/g' > f2 & cat f1 f2 rm f1 f2
我想知道是否可以避免臨時 fifo 或文件。
GNU Parallel 擁有
--tee
並且--keep-order
您可以強制訂單保持不變:ell() { grep -o ell | tr 'a-z' 'A-Z' } orld() { grep orld | sed 's/orl/ORL/g' } export -f ell export -f orld echo "Hello\nWorld" | parallel -k --tee --pipe ::: ell orld
但是,它確實在幕後使用了 fifos 和 tempfiles。但是,如果您的目標只是不必自己處理,那麼它可能是一個解決方案。
此解決方案使用 tmpfiles,但它們幾乎立即取消連結:
myfunc1() { grep -o ell | tr 'a-z' 'A-Z'; } myfunc2() { grep orld | sed 's/orl/ORL/g'; } touch tmp1 tmp2 ( echo "Hello\nWorld" | tee >( (rm tmp1; myfunc1) > tmp1 ) | (rm tmp2; myfunc2) > tmp2 cat <&3 cat <&4 ) 3< tmp1 4< tmp2
或更短:
( rm tmp1 tmp2 echo "Hello\nWorld" | tee >( grep -o ell | tr 'a-z' 'A-Z' >&5 ) | grep orld | sed 's/orl/ORL/g' >&6 cat <&3 cat <&4 ) 5> tmp1 6> tmp2 3< tmp1 4< tmp2
有沒有一種簡單的方法來確保它們符合預期的順序,而不必使用臨時文件/命名的 fifos?可能打開一些文件描述符重定向會有所幫助嗎?
並不真地。和
>(...)
子...|...
shell 並行執行。此外,unix 管道/終端/流套接字/等不是保留邊界的——不能保證單次寫入不會在另一端變成多次讀取(反之亦然)。為了強制執行某些命令,您可以使用諮詢鎖定——查看
flock(1)
和flock(2)
聯機幫助頁。subshell
如何使這項工作在很大程度上取決於mainshell
程序的工作方式。盲目地鎖定非協作程序很容易導致死鎖(如果它確實有效)。