Pipe

管道生產者如何告訴管道消費者它已經到達’文件結尾’?”(未命名管道,未命名管道)

  • September 2, 2017

我有一個應用程序需要生產者將文件名發送給消費者,並讓生產者在發送最後一個文件名並且到達文件末尾時向**消費者指示。

為簡單起見,在以下範例中,生產者echo使用和 進行展示printf,而消費者使用 進行展示cat。我試圖推斷“here file”方法但沒有成功,<<EOF用於向生產者包裝器(如果存在這樣的東西)指示要查找的內容作為文件結束的指示。如果它有效,應該從輸出中cat過濾。EOF

例 1)

輸入

{
echo "Hello World!" 
printf '\x04' 
echo "EOF"
} <<EOF |\
cat

輸出

bash: warning: here-document at line 146 delimited by end-of-file (wanted `EOF')
Hello World!
EOF

例 2)

輸入

{ 
echo "Hello World!" 
printf '\x04' 
echo "EOF"
} |\
cat <<EOF

輸出

bash: warning: here-document at line 153 delimited by end-of-file (wanted `EOF')

用於指示分隔符的“here files”方法僅適用於靜態文本而不適用於動態創建的文本是否正確?

– 實際應用 –

inotifywait -m --format '%w%f' /Dir |  <consumer>

消費者正在等待將文件寫入目錄 /Dir。如果在寫入文件“/Dir/EOF”時,消費者只需通過編寫如下 shell 腳本來檢測邏輯文件結束條件,那就太好了:

inotifywait -m --format '%w%f' /Dir |<</Dir/EOF  <consumer>

– 回應 Giles 的回答 –

理論上可以實現嗎

cat <<EOF
hello
world
EOF

作為

SpecialSymbol="EOF"
{
   echo hello
   echo world
   echo $SpecialSymbol
} |\
while read Line; do 
 if [[ $Line == $SpecialSymbol ]]
   break
 else 
   echo $Line
 fi
done |\
cat

理論上可能,我的意思是*“它會支持現有的使用模式並且只啟用以前非法語法的額外使用模式嗎?”* - 意味著不會破壞現有的法律法規。

對於管道,一旦所有生產者都關閉了對管道的文件描述符並且消費者已經讀取了所有數據,消費者就會看到文件的結尾。

所以,在:

{
 echo foo
 echo bar
} | cat

cat一旦第二個echo終止並cat讀取了foo\n和 ,就會看到文件結尾bar\n。你沒有什麼可做的了。

但是要記住的是,如果管道左側的某些命令啟動了某個後台程序,則該後台程序將繼承管道的 fd(其標準輸出),因此cat在該程序也死之前不會看到 eof或關閉其標準輸出。如:

{
 echo foo
 sleep 10 &
 echo bar
} | cat

您會看到cat在 10 秒過去之前沒有返回。

在這裡,您可能希望將sleep的標準輸出重定向到其他內容,例如/dev/null如果您不希望將其(非)輸出饋送到cat

{
 echo foo
 sleep 10 > /dev/null &
 echo bar
} | cat

如果您希望在執行左側子shell 中的最後一個命令之前關閉管道的寫入端|,您可以使用 關閉stdout 或重定向到子shell 中間的該子shell exec,例如:

{
 echo foo
 exec > /dev/null
 sleep 10
} | (cat; echo "cat is now gone")

cat但是請注意,除了命令之外,大多數 shell 仍將等待該子 shell 。因此,雖然您會cat is now gone立即看到(foo閱讀後),但您仍然需要等待 10 秒才能完成整個管道。當然,在上面的那個例子中,寫它會更有意義:

echo foo | cat
sleep 10

<<ANYTHING...content...ANYTHING是一個here-document,它是使命令的stdin成為一個包含內容的文件。在那裡用處不大。\4是一個字節,當從終端讀取時,將終端設備保存的數據刷新到從它讀取的應用程序(當沒有數據時,read()返回 0,表示文件結束)。同樣,在這裡沒有任何用處。

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