如果在其中创建错误或其创建的任何后台作业中,则退出bash脚本

Dan*_*ott 3 bash shell build-process npm

背景

我正在研究一个bash脚本,以自动化构建位于同一目录中的六个项目的过程.每个项目都有两个要运行的脚本来构建它:

npm install
npm run build
Run Code Online (Sandbox Code Playgroud)

第一行将从npm获取所有依赖项.由于此步骤耗时最长,并且由于项目可以同时获取其依赖项,因此我使用后台作业来并行获取所有内容.(即:npm install &)

第二行将使用这些依赖项来构建项目.因为这必须在所有步骤1完成之后发生,所以我wait在中间运行命令.请参阅下面的代码段.

问题

我想在任何后台作业或npm run build之后发生的步骤中发生错误时立即退出脚本.

我正在使用set -e,但这不适用于后台作业,因此如果一个项目无法安装它的依赖项,其他一切都会继续.

这是我的脚本现在看起来如何的简化示例.

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
Run Code Online (Sandbox Code Playgroud)

同样,如果在任何时候发生错误,我不想继续在脚本中执行任何操作,这适用于父作业和后台作业.这可能吗?

Cha*_*ffy 5

收集后台作业的PID; 然后,用于wait收集每个的退出状态,在该循环中轮询的任何PID第一次退出非零.

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
Run Code Online (Sandbox Code Playgroud)

上述内容虽然简单,但有一点需要注意:如果列表中较晚的项目在列表中较早的项目之前退出非零,则在轮询列表中的该点之前不会观察到这一点.要解决此警告,您可以反复遍历整个列表:

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
Run Code Online (Sandbox Code Playgroud)

但是,因为这个民意调查,它会产生额外的开销.这可以通过捕获SIGCHLD并jobs -n在触发陷阱时引用(以获取自先前轮询后状态已更改的作业列表)来避免.


归档时间:

查看次数:

1902 次

最近记录:

9 年,9 月 前