在我的shell脚本中,如果几个嵌套函数并发运行并失败,脚本不会失败。
status() {
exit_st=$1
error_1=$2
if ! [[ $exit_st -eq 0 ]]; then
echo "[ERROR] - ${error_1}"
exit 1
else
echo "[INFO] - ${error_1}"
fi
}
abc(){
val1= $1
val2= $2
#Some SQL command here
status $? "SQL command step"
}
abc cmd1 cmd2 &
abc cmd3 cmd4 &
wait
echo 'hi'
在上面的代码中,如果#Some SQL command here
上的命令失败,则脚本不会退出并继续打印hi
。我尝试将exit
更改为return
,但它不会出错。我希望如果任何abc
作业失败,那么整个脚本应该退出非零代码。
我的bash版本是GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
,所以我无法使用wait -n
选项
1条答案
按热度按时间gmxoilav1#
当后台进程以非零状态退出时,即使
set -e
(set -o errexit
)处于活动状态,Bash也不会自动退出。如果您希望您的程序在后台进程失败时退出,那么您需要显式地检测失败。如果你有Bash 43(2014年发布)或更高版本,然后您可以在问题中的代码中通过替换
与
wait
的-n
选项。3.导致wait
等待下一个后台进程退出,并返回其状态。wait -n
返回非零状态;或者是因为后台进程以非零状态退出,或者是因为所有后台进程都以零状态退出。wait -n
的更多信息,以及有关在Bash中处理后台进程的一般信息,请参见ProcessManagement - Greg's Wiki。页面上说在使用wait -n
的程序中运行set -m
。我还没有发现这是必要的,但这可能是因为我使用的是更晚的Bash版本。YMMV。尽管
while wait ...
循环允许程序在后台进程失败时继续运行(例如,在后台进程失败时)。例如,它可以调用exit
),它可能会让其他后台进程仍然运行,即使在主程序退出后。这可能导致不需要的处理和/或对终端的意外输出。您可能希望在while wait ...
循环终止后终止所有剩余的后台进程。一种方法是:jobs
命令为每个活动的后台进程输出一行。每行以方括号中的作业编号开始。请参阅删除字符串的一部分(BashFAQ/100(How do I do string manipulation in bash?)),以了解${line#*\[}
和${jobnum%%\]*}
(用于从行中提取作业号)的说明。Bash的版本超过4。3我管理后台进程的首选选项是在轮询循环中使用jobs命令。
这是一个,Shellcheck-干净的,修改过的程序版本,它演示了该技术:
printf
而不是echo
)。bgpids
来保存后台进程的PID列表。wait_for_pids
和kill_running_jobs_and_exit
。wait
替换为wait_for_pids "${bgpids[@]}" || kill_running_jobs_and_exit "$?"
。run_sql_command "$val1" "$val2"
替换为适合您的任何内容。我编写并使用了一个名为run_sql_command
的函数进行测试。sleep 1
)。有些东西可能对你更好(E)。例如sleep 10
或(如果sleep
支持浮点参数)sleep 0.1
)。is_active_pid
数组的信息,请参见BashGuide/Arrays - Greg's Wiki的稀疏数组部分。${active_pids[@]+"${active_pids[@]}"}
而不是"${active_pids[@]}
来解决旧版本Bash中的一个错误,该错误导致它在set -o nounset
(set -u
)生效时错误处理空数组。参见bash empty array expansion with 'set -u'。