如果它发生错误或任何后台作业它创建退出bash脚本 [英] Exit a bash script if an error occurs in it or any of the background jobs it creates

查看:128
本文介绍了如果它发生错误或任何后台作业它创建退出bash脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我工作的一个bash脚本来自动构建生活在同一个目录下半打项目的过程。每个项目都有两个脚本,以便构建它运行:

I'm working on a bash script to automate the process of building half a dozen projects that live in the same directory. Each project has two scripts to run in order to build it:

npm install
npm run build

第一行会获取所有依赖从NPM。由于这一步需要的时间最长,因为项目可以同时获取它们的依赖,我使用的后台作业获取并行的一切。 (即: NPM安装和放大器;

第二行将使用这些依赖关系来构建项目。由于这必须发生后,所有的步骤完成1秒,我在两者之间运行命令。请参见下面code片段。

The second line will use those dependencies to build the project. Since this must happen after all the Step 1s finish, I'm running the wait command in between. See code snippet below.

问题

我想尽快有我的脚本的退出在任何后台作业时发生错误,或者发生之后的 NPM运行构建一步。

I would like to have my script exit as soon as an error occurs in any of the background jobs, or the npm run build step that happens afterward.

我用设置-e ,然而这并不适用于后台作业,因此如果一个项目未能安装它的依赖,一切源源不绝。

I'm using set -e, however this does not apply to the background jobs, and thus if one project fails to install it's dependencies, everything else keeps going.

下面是我的脚本的外观,现在一个简单的例子。

Here is an simplified example of how my script looks right now.

build.sh

set -e

DIR=$PWD

for dir in ./projects/**/
do
    echo -e "\033[4;32mInstalling $dir\033[0m"
    cd $dir
    npm install & # takes a while, so do this in parallel
    cd $DIR
done

wait # continue once the background jobs are completed

for dir in ./projects/**/
do
    cd $dir
    echo -e "\033[4;32mBuilding $dir\033[0m"
    npm run build # Some projects use other projects, so build them in series
    cd $DIR
    echo -e "\n"
done

同样,我也不想继续在脚本中做任何事情,如果在任何时候发生错误,这同样适用于父母和后台作业两者。这可能吗?

Again, I don't want to continue doing anything in the script if an error occurs at any point, this applies to both the parent and background jobs. Is this possible?

推荐答案

收集的PID为后台作业;然后,使用收集各的退出状态,退出第一次的PID在这个循环在调查非零。

Collect the PIDs for the background jobs; then, use wait to collect the exit status of each, exiting the first time any PID polled over in that loop is nonzero.

install_pids=( )
for dir in ./projects/**/; do
  (cd "$dir" && exec npm install) & install_pids+=( $! )
done
for pid in "${install_pids[@]}"; do
  wait "$pid" || exit
done

以上,虽然简单,有一个警告:如果一个项目的的列表中退出之前的项目列表中较早为零,这将无法观察到列表中的那点轮询。要解决此警告,可以通过整个列表反复迭代:

The above, while simple, has a caveat: If an item late in the list exits nonzero prior to items earlier in the list, this won't be observed until that point in the list is polled. To work around this caveat, you can repeatedly iterate through the entire list:

install_pids=( )
for dir in ./projects/**/; do
  (cd "$dir" && exec npm install) & install_pids+=( $! )
done
while (( ${#install_pids[@]} )); do
  for pid_idx in "${!install_pids[@]}"; do
    pid=${install_pids[$pid_idx]}
    if ! kill -0 "$pid" 2>/dev/null; then # kill -0 checks for process existance
      # we know this pid has exited; retrieve its exit status
      wait "$pid" || exit
      unset "install_pids[$pid_idx]"
    fi
  done
  sleep 1 # in bash, consider a shorter non-integer interval, ie. 0.2
done

但是,因为此调查,它招致额外的开销。这可以通过捕获SIGCHLD并参照工作-n 避免(获得的就业机会,其地位,因为前姓改列表)当陷阱被触发。

However, because this polls, it incurs extra overhead. This can be avoided by trapping SIGCHLD and referring to jobs -n (to get a list of jobs whose status changed since prior poll) when the trap is triggered.

这篇关于如果它发生错误或任何后台作业它创建退出bash脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆