
在 shell 腳本中,我想使用命名管道寫入外部進程 X 的 stdin,並且想將 stdout/stderr 從另一個命名管道傳送到目前終端。
外部進程 X 透過 PIPEIN 接收 stdin 並將其 stdout/stderr 傳送至 PIPEOUT。
tail -f $(tail -F PIPEOUT) & # (1) this is completely wrong, need help here
for i; do
echo "${i}" > PIPEIN # send stdin to X
done
echo "[stdin end]" > PIPEIN # signal that we are done writing (there might be a better way lol)
所以在上面的腳本中,我們已經啟動了進程X,它已經運行了一段時間。但現在,當我們執行上面的腳本時,我們想要向 X 發送一些標準輸入,並且我們想要使用 PIPEOUT 從進程 X 中讀取標準輸出。
我上面想做的是在將 stdin 發送到 X 之前設定對 PIPEOUT 的讀取,以確保捕獲 X 的所有 stdout/stderr 。並將該stdio 傳送到目前終端。
有誰知道我在說什麼。如果我沒有記錯的話,我只需要修復標記為(1) 的行,並以某種方式在後台設定一個讀取,可以從PIPEOUT 讀取並將該stdio 以某種方式發送到當前終端/tty 。
答案1
我不清楚你想做什麼tail -f $(tail -F PIPEOUT) &
。這是tail -f
ing 文件是的結果 tail -F
,通常永遠不會終止。我的假設是您希望輸出通過管道的所有內容,無論需要多長時間。
just 的問題tail -f
是它必須在輸出任何內容之前找到文件的末尾,而對於管道來說這永遠不會發生。你可以給出tail
一個明確的起點,而不是-n +x
,選擇起始行(從頭開始,從 1 開始索引)。tail -n 1 -f foo
將顯示它可以從中獲取的所有內容foo
。
tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
for i in a b c d ; do
echo $i > PIPEIN
done
echo "[stdin end]" > PIPEIN
但請注意,這echo > foo
將在寫入該行後關閉 foo — 另一端的命令需要樂意處理該問題。如果這個例子是人為的並且真實的輸入來自其他地方,你可以忽略它。
另請注意該tail
過程永遠不會終止——它一直期待著更多的東西可能會通過管道。您必須自己明確地殺死它,也許可以使用 shell 的作業控制。如果輸出中有某種模式表明它已完成,您可能會發現retail
(「有正規表示式的尾部」)有用 -retail -n +1 -f -u REGEX PIPEOUT
當出現符合的行時將終止REGEX
。(作為免責聲明,我retail
幾年前為此目的撰寫了這篇文章)
答案2
僅開啟 PIPEIN 進行寫入一次,程式就會終止 - 即使有 2 秒的延遲:
mkfifo PIPEIN PIPEOUT
tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
(
for i in a b c d ; do
echo $i
done
sleep 2
echo "[stdin end]"
) > PIPEIN
如果您多次開啟 fifo,則 fifo 的讀取器可能會認為它已關閉,因此寫入器將被掛起,直到另一個讀取器從 fifo 讀取資料。
所以保存的賭注是只打開 PIPEIN 一次。否則您可能會看到程式鎖定。