并行运行子 shell 并收集退出代码

并行运行子 shell 并收集退出代码

我有以下内容,我认为它并行运行子 shell,但实际上似乎串行运行它们,我不明白为什么:

#!/usr/bin/env bash

set -e;
set -m # allow for job control


EXIT_CODE=0;  # exit code of overall script

function handleJobs() {
     for job in `jobs -p`; do
         echo "PID => ${job}"
         CODE=0;
         wait ${job} || CODE=$?
         if [[ "${CODE}" != "0" ]]; then
            echo "At least one process failed with exit code => ${CODE}" ;
            EXIT_CODE=1;
         fi
     done
}

trap 'handleJobs' CHLD


for file in "$HOME/mongodump_dev/cdt_db/"* ; do

  file="$(basename "$file")"

  if [[ "$file" != "system"* && "$file" != "locks"* ]]; then

    mongorestore \
        --db "cdt_dev" \
        --collection "${file%.*}" \
        --host "<my-host>" \
        "$HOME/mongodump_dev/cdt_db/$file"  &

  fi;

done


wait;
echo "exit code => $EXIT_CODE"
exit "$EXIT_CODE"

有人知道为什么子shell 串联运行吗?

我尝试这样做:

(
        mongorestore \
            --db "cdt_dev" \
            --collection "${file%.*}" \
            --host "<my-host>" \
            "$HOME/mongodump_dev/cdt_db/$file"  &

) &

现在它们并行运行,但现在整个脚本永远不会退出,我担心我实际上没有准确捕获退出代码。

答案1

您编写的脚本存在许多“问题”。我所做的是复制您的脚本,并出于测试和评估的目的,通过执行诸如替换mongorestore为 之类的操作sleep 9999以及插入echo附加到日志文件的跟踪消息来简化它。总而言之,在我看来你并不需要任何陷阱;只需将您的mongorestore声明替换为:

( mongorestore ...
  exit_code=$?
  [ $exit_code -ne 0 ] \
  && printf "Process %s for file %s failed with exit code %s\n" \
       $BASHPID  "${file%.*}" $exit_code
) &

顺便说一句,验证所有子进程是否已并行生成的简单方法是打开另一个终端并运行pgrep -a mongorestore.

另外,在我看来,在脚本末尾使用 EXIT_CODE 永远不应该有值,因此您的exit命令应该因某种错误而失败,这意味着您的脚本总是会因错误而退出。

相关内容