Shell脚本中调用spark-submit无法捕获正确退出码的解决方法咨询
问题原因
当使用--deploy-mode cluster时,本地的spark-submit进程仅负责将任务提交到YARN集群,提交动作完成后就会退出,它的退出码仅代表「任务是否成功提交到YARN」,而非「任务本身是否执行成功」。这就是为什么即使后续任务执行失败,脚本里的$?仍返回0——因为提交动作已经成功完成了。
你直接在Shell执行时能拿到非零退出码,大概率是混淆了执行场景(比如误使用了client模式),或者直接执行时提交动作本身就失败了(比如参数错误、Jar包不存在等)。
解决方案
根据需求,有两种可行方案:
方案1:切换到YARN Client模式(优先推荐,若业务允许)
如果业务场景允许Driver运行在本地机器(而非YARN容器),只需将部署模式改为client:
spark-submit --class my.App --master yarn --deploy-mode client ./Spark_job.jar
此时spark-submit进程会一直等待Driver执行完成,它的退出码会直接反映任务的执行结果——任务失败则返回非零值,成功返回0,脚本里直接用$?就能捕获正确状态。
方案2:Cluster模式下通过YARN命令检查任务状态(必须用Cluster模式时)
如果必须使用Cluster模式,需要通过YARN的命令行工具跟踪任务的最终执行状态:
提交任务并捕获应用ID
提交时提取YARN返回的应用ID(application_xxxx_xxxx格式):# 捕获spark-submit的输出 submit_output=$(spark-submit --class my.App --master yarn --deploy-mode cluster ./Spark_job.jar) # 从输出中提取应用ID app_id=$(echo "$submit_output" | grep -oP 'application_\d+_\d+') # 检查是否成功提取到应用ID(如果提交失败,这里会为空) if [[ -z "$app_id" ]]; then echo "任务提交失败" exit 1 fi轮询等待任务结束并检查最终状态
通过yarn application -status命令轮询任务状态,直到任务进入终态:while true; do # 获取任务的最终状态(SUCCEEDED/FAILED/KILLED等) final_status=$(yarn application -status "$app_id" | grep -oP 'Final Status: \K\w+') # 当状态不是UNDEFINED时,说明任务已结束 if [[ "$final_status" != "UNDEFINED" ]]; then break fi # 每10秒轮询一次 sleep 10 done根据最终状态设置退出码
if [[ "$final_status" == "SUCCEEDED" ]]; then echo "任务执行成功" exit 0 else echo "任务执行失败,状态:$final_status" exit 1 fi
补充说明
你之前尝试用exit_code=$(spark-submit ...)是错误的——$()捕获的是命令的标准输出内容,而退出码是存储在$?变量中的。但即使你当时直接看$?,在Cluster模式下也只能得到提交动作的结果,而非任务执行结果,这就是问题的核心。
内容的提问来源于stack exchange,提问作者Gestalt

