如果它发生错误或任何后台作业它创建退出bash脚本 [英] Exit a bash script if an error occurs in it or any of the background jobs it creates
问题描述
背景
我工作的一个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屋!