等待管道中的進程返回錯誤的退出代碼

等待管道中的進程返回錯誤的退出代碼

我一定在這裡遺漏了一些東西:

#!/bin/bash
timeout 5 sleep 10 &
parent_pid=$( ps --pid $! -o ppid --no-headers )
timeout_pid=$( pgrep --parent $parent_pid timeout )
wait $timeout_pid
echo "exit code: $?"

呼叫腳本wait-pid並運行:

$ ./wait-pid 
exit code: 124

這是我所期望的,timeout殺死sleep進程並以 124 退出,它wait會盡職地返回。

但是如果我向初始命令添加管道:

timeout 5 sleep 10 | cat &
parent_pid=$( ps --pid $! -o ppid --no-headers )
timeout_pid=$( pgrep --parent $parent_pid timeout )
wait $timeout_pid
echo "exit code: $?"

現在我得到:

$ ./wait-pid 
exit code: 0

不應該wait仍然返回它正在等待的進程的退出代碼:timeout。那麼退出代碼不應該還是 124 嗎?

這是 bash 4.4.20(1)-release 的版本。

答案1

我在 bash 郵件清單上收到了來自知識淵博的 Greg Wooledge 的回覆。關鍵要素是:

wait 指令僅適用於 shell 的直接子進程,也稱為「非同步命令」。如果您的非同步指令是管道,我們將回退到原始的 sh 功能集。非同步指令的退出狀態是管線中最後一個指令的退出狀態,其他指令的退出狀態將被簡單地丟棄。

所以這就是為什麼我沒有得到timeout它在管道中時的退出代碼。

獲得我想要的行為的方法是使用臨時檔案從非同步程式碼中捕獲退出代碼。就像是:

{
  timeout 5 sleep 10 | cat
  echo "${PIPESTATUS[@]}" > "$tempfile"
} &
wait

相關內容