Pipe

當左命令產生大輸出時,如何在破折號中檢查左命令在管道“左|右”中的退出狀態

  • October 1, 2018

似乎變數“PIPESTATUS”在dash. 簡單的單獨執行不起作用,因為左側命令會產生非常大的輸出。我使用了一個fifo來完成這個任務:

#!/bin/dash
mkfifo command1 command2
dash -c "cat ./content;code=\${?};echo \${code} > command1 &" | dash -c "md5sum;code=\${?};echo \${code} > command2 &"
echo "$(cat ./command1)" "$(cat ./command2)"

但我不知道為什麼它掛了?

您可以使用命名管道並手動連接兩個程序。以相反的順序啟動它們,因此左側在前台執行,您可以$?像往常一樣獲得其退出狀態。

#!/bin/sh
dir=$(mktemp -d)
mkfifo "$dir/p"
cat < "$dir/p" > /dev/null &
( echo foo; exit 12; ) > "$dir/p"
echo "exit status: left: $?"
rm -r "$dir"

或者如果你想要兩者,獲取後台程序的 PID$!wait獲取退出狀態。

#!/bin/sh
dir=$(mktemp -d)
mkfifo "$dir/p"
( echo foo; exit 12; ) > "$dir/p" &          # left-hand side
pidleft=$!
( cat; exit 34; ) < "$dir/p" > /dev/null &   # right-hand side
pidright=$!
wait "$pidleft"; exitleft=$?
wait "$pidright"; exitright=$?
echo "exit status: left: $exitleft right: $exitright"
rm -r "$dir"

你仍然可以將管道的第二部分留在前景中,我只是想對稱地做。


例如,您還可以將退出狀態儲存到文件中,然後從那裡獲取它們:

#/bin/sh
( somecmd; echo "$?" > exit1 ) | ( cat; echo "$?" > exit2)
echo "exit status: left: $(cat exit1) right: $(cat exit2)"

我認為命名管道在這裡用處不大,因為退出狀態只有幾個字節。exit1在嘗試讀取和exit2第二行之前,shell 將等待管道完成。

如果要改用命名管道,則需要將管道置於後台,因為對管道的寫入會阻塞,直到打開讀取端為止。

#/bin/sh
mkfifo exit1 exit2
( somecmd; echo "$?" > exit1 ) | ( cat; echo "$?" > exit2) &
echo "exit status: left: $(cat exit1) right: $(cat exit2)"

但是,如果cat讀取管道的 s 由於某種原因沒有執行,則寫入它們的子shell 將在後台無限期地阻塞。

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