dolphinschedule使用shell任务结束状态研究

背景:配置的dolphin任务,使用的是shell,shell里包含了spark-submit 如下截图。 

dolphin

 shell

 介绍完毕,开始说明现象。 有天有人调整了集群的cdp配置,executor-cores max=1

我之前这里写的是2,所以spark任务就报错了  spark-submit报错_cclovezbf的博客-CSDN博客

不多说,后面改下这个配置就好了,spark任务就能运行起来。

但是在这个过程中发现了一个很严重很严重的问题。 这个任务失败了,报错了,但是dolphin显示状态居然是成功!!!!!!!!!!!!!!!!!!!

报错1 列数不对 还有资源不够,还有我里面涉及的接口网络超时,都是我自己故意模拟的的

 很明显这里报错了,那么这个dolphin任务就该是失败状态呀。怎么回事??

直接百度!!!

海豚调度任务如何判断任务成功还是失败(源码)?_海豚调度器3.0api访问hive失败_黑眼圈@~@的博客-CSDN博客

 其实我都没怎么看这篇文章,但是还是提示我要去看源码。

AbstractCommandExecutor.java

    public CommandExecuteResult run(String execCommand) throws Exception{

        CommandExecuteResult result = new CommandExecuteResult();


        if (StringUtils.isEmpty(execCommand)) {
            return result;
        }
        //构建工作环境 dolphin 默认的是/tmp/dolphinscheduler/exec/process/588/2877/1284345/1400413
        String commandFilePath = buildCommandFilePath();
        
        //把你在dolphin框框填的command 封装好
        // create command file if not exists
        createCommandFileIfNotExists(execCommand, commandFilePath);
        //创建一个process 准备去执行
        //build process
        buildProcess(commandFilePath);
        //打印输出的内容 其实也就是你在dolphin看到的日志
        // parse process output
        parseProcessOutput(process);

        //获取processid
        Integer processId = getProcessId(process);

        result.setProcessId(processId);

        // cache processId
        taskExecutionContext.setProcessId(processId);
        taskExecutionContextCacheManager.cacheTaskExecutionContext(taskExecutionContext);

        // print process id
        logger.info("process start, process id is: {}", processId);

        // if timeout occurs, exit directly
        long remainTime = getRemaintime();
        //注意这里啊  这里还假装看了下status 其实这个一直为true。
        // waiting for the run to finish
        boolean status = process.waitFor(remainTime, TimeUnit.SECONDS);


        logger.info("process has exited, execute path:{}, processId:{} ,exitStatusCode:{}",
                taskExecutionContext.getExecutePath(),
                processId
                , result.getExitStatusCode());

        // if SHELL task exit  //这里一直为true
        if (status) {
            // set appIds
            List<String> appIds = getAppIds(taskExecutionContext.getLogPath());
            result.setAppIds(String.join(Constants.COMMA, appIds));

            // SHELL task state
            result.setExitStatusCode(process.exitValue());

            // if yarn task , yarn state is final state
            if (process.exitValue() == 0){
                result.setExitStatusCode(isSuccessOfYarnState(appIds) ? EXIT_CODE_SUCCESS : EXIT_CODE_FAILURE);
            }
        } else {
            logger.error("process has failure , exitStatusCode : {} , ready to kill ...", result.getExitStatusCode());
            ProcessUtils.kill(taskExecutionContext);
            result.setExitStatusCode(EXIT_CODE_FAILURE);
        }


        return result;
    }

        if (status) { //这里一直为true 
            // set appIds  //获取application_id ,这里也吊的很,他是根据正则:application_ 去在打印输出的日志里 查这个application_id  我怀疑你echo 这个 他估计也要去查
            List<String> appIds = getAppIds(taskExecutionContext.getLogPath());
            result.setAppIds(String.join(Constants.COMMA, appIds));

            // SHELL task state 

// 这个exitValue比较重要,这个就是看shell最后退出的状态是什么?正常为0 其余都是失败
            result.setExitStatusCode(process.exitValue());

            // if yarn task , yarn state is final state

            //这里是说 shell正常退出了,执行成功了,我就去根据application_id去看任务是否失败  但是这里注意啊 我看了我们生产环境的common.properties没有配置rm的地址,他是怎么取请求rm的url 去获取yarn状态的呢? 所以这里我保留存疑,我看了日志根本就没有看到请求yarn获取状态。
            if (process.exitValue() == 0){ 
                result.setExitStatusCode(isSuccessOfYarnState(appIds) ? EXIT_CODE_SUCCESS : EXIT_CODE_FAILURE);
            }
        } 

这里我总结下dolphin判断任务的成功和失败。

shell 成功, 去看yarn是否失败, yarn任务成功 dolphin状态显示成功 否则就失败。

shell 失败, 那么dolphin就是失败。

看着很简单,但是这里又涉及到两个知识点

1.什么情况下shell叫成功呢?

其实上面说的不太对,

shell 成功= shell结束后的 exitCode=0

shell 失败= shell结束后的 exitCode!=0

 2.set -e 的作用

 简单的来说, 加了set -e 程序在遇到错误的时候就会停止,就是会抛异常。不加的话 程序会一直往下执行。

#set -e 
echo 1
ls/chenchi
echo 2

 好了介绍完毕,开始复现dolphin出现这个问题的原因。

cc_no_set.sh

#set -e

spark-submit error

cc_with_set.sh

set -e

spark-submit error

cc.sh

echo "success"

with_set_cc.shbash /data/DATA_DIR/share/dw_kpi/shell/cc_with_set.sh 
bash /data/DATA_DIR/share/dw_kpi/shell/cc.sh
成功
no_set_cc.shbash /data/DATA_DIR/share/dw_kpi/shell/cc_no_set.sh 
bash /data/DATA_DIR/share/dw_kpi/shell/cc.sh
成功
with_set.shbash /data/DATA_DIR/share/dw_kpi/shell/cc_with_set.sh 
 
失败
no_set.shbash /data/DATA_DIR/share/dw_kpi/shell/cc_no_set.sh 
 
失败

可以看到吧 这里为啥 我加了一个 bash cc.sh 就成功了?

因为dolphin 将两条命令 组装为一个shell

bash fail.sh

bash succes.sh

注意这里是没有加 set -e 的,说明程序执行了fail.sh后还是会继续执行succse.sh,这。。。。最后的结果肯定就是success。

真是他妈的一个大坑。 dolphin的任务状态是由什么决定的?

就是由你最后一条命令的状态决定的。

但是有的小伙伴又说了。 我有时候就是要两个任务搞到一起 ,

bash 1.sh

bash 2.sh

然后 我想 前面的1.sh失败了就不执行后面的2.sh了。 而不是像现在这样 1.sh失败 继续执行2.sh,

2.sh成功,最后dolphin的任务状态也成功。

很简单 你再加一句。

set -e 

bash 1.sh

bash 2.sh

这样即可。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Unix或Linux系统中,你可以使用shell脚本来创建一个定时任务,让某个命令或脚本在特定时间点或按照一定的时间间隔自动执行。这个过程通常涉及到cron定时器服务。 1. **crontab文件**:每个用户都有一个名为`.crontab`的文件,用于配置cron任务。你可以用文本编辑器打开这个文件(如`crontab -e`)来添加新的定时任务。 2. **定时表达式**:在`.crontab`文件中,你需要定义一个定时表达式,它由五个字段组成,分别代表: - 分钟(0-59) - 小时(0-23) - 天(1-31) - 月份(1-12) - 周(0-7,其中0和7都代表周日) 例如,`0 1 * * *`表示每天的凌晨1点执行任务。 3. **添加任务**:添加一个新的任务行,格式通常是: ``` * * * * * /path/to/your/script.sh ``` 其中,`/path/to/your/script.sh`替换为你的shell脚本的实际路径。 4. **保存并激活**:完成编辑后,记得使用`crontab -u <username> -l > new_crontab`将更改保存到新的文件,再用`crontab -u <username> new_crontab`命令使更改生效,这里`<username>`是你的用户名。 如果你需要在预定时间结束后自动停止任务,这取决于你的脚本如何设计。通常,你可以通过在脚本中添加条件判断,比如计数器或检查某个标志来控制何时结束任务。如果没有直接的机制,你可能需要额外的逻辑处理或者使用进程管理工具(如`pkill`)来终止脚本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值