
我有一個程序,在讀取給定流中的 EOF 時自動退出(在以下情況下為 stdin )。
現在我想製作一個 shell 腳本,它會建立一個命名管道並將程式的標準輸入連接到它。然後腳本寫入管道幾次使用echo
and cat
(以及其他退出時自動產生 EOF 的工具)。我面臨的問題是,當第一個echo
完成時,它會向管道發送一個 EOF 並使程式退出。如果我使用類似的東西tail -f
,那麼當我打算退出程式時我無法發送 EOF。我正在研究一個平衡的解決方案,但無濟於事。
我已經找到如何防止 EOF 以及如何手動發送 EOF,但我無法將它們結合。有什麼提示嗎?
#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg
答案1
正如其他人所指出的,一旦沒有寫入者,管道的讀取器就會收到 EOF。因此,解決方案是確保始終有作家將其打開。該作者不必發送任何內容,只需將其打開即可。
由於您使用的是 shell 腳本,最簡單的解決方案是告訴 shell 開啟管道進行寫入。然後完成後關閉它。
#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3
請注意,如果省略最後一行,則當腳本退出時,檔案描述符 3 將自動關閉(因此讀取器會收到 EOF)。除了方便之外,如果腳本以某種方式提前終止,這也提供了某種安全性。
答案2
當最後一個寫入者消失時,管道會收到 EOF。為了避免這種情況,請確保始終有一個寫入器(一個打開管道進行寫入但實際上不寫入任何內容的進程)。要發送 EOF,請讓保留寫入者消失。
mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
kill $P_writer_pid
}
答案3
程式無法區分 EOF 表示“是時候退出了”,而 EOF 表示“編寫完成,但可能還有其他人的輸入”。
如果您有能力修改程式的行為,則可以在無限循環中進行讀取(一次迭代持續到 EOF),並向其發送表示「退出時間」的特定命令字串。發送該字串將是send_eof
您問題中的命令的任務。
另外一個選擇:
( echo some stuff; cat more_stuff.txt ) >P
或者
{ echo some stuff; cat more_stuff.txt; } >P