從子 shell 讀取 stdout/stderr 到父 shell

從子 shell 讀取 stdout/stderr 到父 shell

在 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 -fing 文件是的結果 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 一次。否則您可能會看到程式鎖定。

相關內容