Bash

收集並行後台程序(子shell)的退出程式碼

  • April 6, 2021

假設我們有一個像這樣的 bash 腳本:

echo "x" &
echo "y" &
echo "z" &
.....
echo "Z" &
wait

有沒有辦法收集子外殼/子程序的退出程式碼?尋找方法來做到這一點,找不到任何東西。我需要並行執行這些子shell,否則會更容易。

我正在尋找一個通用的解決方案(我有一個未知/動態數量的子程序要並行執行)。

Alexander Mills 使用 handleJobs 的答案給了我一個很好的起點,但也給了我這個錯誤

警告:run_pending_traps:trap_list 中的值錯誤

$$ 17 $$: 0x461010

這可能是一個 bash 競爭條件問題

相反,我只是儲存每個孩子的 pid 並等待並專門為每個孩子獲取退出程式碼。我發現這個更乾淨的子程序在函式中產生子程序並避免等待我打算等待子程序的父程序的風險。它更清楚發生了什麼,因為它沒有使用陷阱。

#!/usr/bin/env bash

# it seems it does not work well if using echo for function return value, and calling inside $() (is a subprocess spawned?) 
function wait_and_get_exit_codes() {
   children=("$@")
   EXIT_CODE=0
   for job in "${children[@]}"; do
      echo "PID => ${job}"
      CODE=0;
      wait ${job} || CODE=$?
      if [[ "${CODE}" != "0" ]]; then
          echo "At least one test failed with exit code => ${CODE}" ;
          EXIT_CODE=1;
      fi
  done
}

DIRN=$(dirname "$0");

commands=(
   "{ echo 'a'; exit 1; }"
   "{ echo 'b'; exit 0; }"
   "{ echo 'c'; exit 2; }"
   )

clen=`expr "${#commands[@]}" - 1` # get length of commands - 1

children_pids=()
for i in `seq 0 "$clen"`; do
   (echo "${commands[$i]}" | bash) &   # run the command via bash in subshell
   children_pids+=("$!")
   echo "$i ith command has been issued as a background job"
done
# wait; # wait for all subshells to finish - its still valid to wait for all jobs to finish, before processing any exit-codes if we wanted to
#EXIT_CODE=0;  # exit code of overall script
wait_and_get_exit_codes "${children_pids[@]}"

echo "EXIT_CODE => $EXIT_CODE"
exit "$EXIT_CODE"
# end

wait與 PID 一起使用,它將:

等待每個程序 ID pid或作業規範jobspec指定的子程序退出,並返回最後等待的命令的退出狀態。

您需要隨時保存每個程序的 PID:

echo "x" & X=$!
echo "y" & Y=$!
echo "z" & Z=$!

您也可以在腳本中啟用作業控制set -m並使用作業%n規範,但您幾乎可以肯定不希望 -作業控制有很多其他副作用

wait將返回與完成的過程相同的程式碼。您可以wait $X在任何(合理的)以後使用來訪問最終程式碼,$?或者簡單地將其用作真/假:

echo "x" & X=$!
echo "y" & Y=$!
...
wait $X
echo "job X returned $?"

wait如果命令尚未完成,將暫停直到命令完成。

如果您想避免這樣的停頓,您可以設置 a traponSIGCHLD,計算終止次數,並在所有waits 都完成後立即處理它們。您wait幾乎可以一直單獨使用。

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