xxl-job-代码创建任务执行本地命令+解决报错

news2024/12/24 22:01:22

问题描述

因为环境受限,所以我的mysql和xxl-job-admin是放在docker里的,执行器是放在本地的,要执行的命令也需要本地环境。

本文将记录相关配置、实现过程和遇到的问题及解决方案。

配置

xxl-job-admin配置

xxl-job-admin放在docker容器里跑,可能需要修改的配置如下:

server.port=8080
# 第二个mysql替换localhost,因为我的mysql也是放在docker容器的,名字就是mysql
spring.datasource.url=jdbc:mysql://mysql:3306/xxl_job?&autoReconnect=true&useSSL=false
# username password自己填
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

xxl-executor

直接使用xxl-job-executor-sample-springboot,不作修改,在local跑。

Service

service是代码创建和触发任务的核心代码。位置随便放,哪里需要放哪里。

这里的任务是执行一段命令,类似

cd /xxx/xx && python xx.py

因为我需要使用BEAN模式,所以任务参数(executorParam)里填的应该是写这段命令的shell脚本(cmd.sh),如果executor找不到这个shell脚本,会报错。成功创建的任务,在网页上应该是这种状态:
在这里插入图片描述
下面是service代码:


	public String getCookie(String url, String userName, String password) {
		if (this.cookie.length() > 0) {
        	return this.cookie;
        }
		String path = url;
        Map<String, Object> hashMap = new HashMap();
        hashMap.put("userName", userName);
        hashMap.put("password", password);
        HttpResponse response = HttpRequest.post(path).form(hashMap).execute();
        List<HttpCookie> cookies = response.getCookies();
        StringBuilder sb = new StringBuilder();
        for (HttpCookie cookie : cookies) {
            sb.append(cookie.toString());
        }
        this.cookie = sb.toString();
        return this.cookie;
	}


	public void setCookie(String cookie) {
		this.cookie = cookie;
	}


	public void triggerDynamicJob(String url, int id, String cmdStr) {
		String requestUrl = url;
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("id", id);
		paramMap.put("executorParam", cmdStr);
		paramMap.put("addressList", "");
		HttpResponse response = HttpRequest.post(requestUrl).form(paramMap).cookie(this.cookie).execute();
		if (HttpStatus.HTTP_OK != response.getStatus()) {
        	return;
        }
        JSONObject jsonObject = new JSONObject(response.body());	
        System.out.println(jsonObject.toString());
	}


	public void delDynamicJob(String url, int id) {
		String requestUrl = url + String.valueOf(id);
		HttpResponse response = HttpRequest.get(requestUrl).cookie(this.cookie).execute();
		if (HttpStatus.HTTP_OK != response.getStatus()) {
        	return;
        }
        JSONObject jsonObject = new JSONObject(response.body());
        //System.out.println(jsonObject.toString());
	}

	
	public int createDynamicJob(String url, String cmdStr) {
		// cmdStr = "print('0')";
        // Prepare request payload
        String requestUrl = url;
        Map<String, Object> paramMap = new HashMap<>();
        // 执行器id
        paramMap.put("jobGroup", 1);
        paramMap.put("jobDesc", "dynamic");
        paramMap.put("scheduleType", "NONE");
        paramMap.put("jobCron", "");
        //paramMap.put("glueType", "GLUE_PYTHON");
        paramMap.put("glueType", "BEAN");
        paramMap.put("author", "pxy");
        paramMap.put("executorRouteStrategy", "FIRST");
        paramMap.put("executorHandler", "commandJobHandler");
        paramMap.put("executorParam", cmdStr);
        paramMap.put("misfireStrategy", "DO_NOTHING");
        paramMap.put("executorBlockStrategy", "SERIAL_EXECUTION");
        paramMap.put("executorTimeout", "0");
        paramMap.put("executorFailRetryCount", "0");
        paramMap.put("glueSource", cmdStr);
        
        HttpResponse response = HttpRequest.post(requestUrl).form(paramMap).cookie(this.cookie).execute();
        //System.out.println("Response: " + response);
        if (HttpStatus.HTTP_OK != response.getStatus()) {
        	return -1;
        }
        JSONObject jsonObject = new JSONObject(response.body());
        int jobId = jsonObject.getInt("content");
        //System.out.println(jobId);
        return jobId;
	}

需要注意的是,代码触发任务时必须要带executorParam。虽然创建时我写了executorParam,在admin网页上手动触发一次,也是能正常执行的,但是代码触发时如果不带executorParam,系统会报错命令为空:

2023-09-14 15:20:55 [com.xxl.job.core.thread.JobThread#run]-[133]-[xxl-job, JobThread-21-1694676055262] 
----------- xxl-job job execute start -----------
----------- Param:
2023-09-14 15:20:55 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[104]-[xxl-job, JobThread-21-1694676055262] java.io.IOException: Cannot run program "": error=2, 没有那个文件或目录
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
	at com.xxl.job.executor.service.jobhandler.SampleXxlJob.commandJobHandler(SampleXxlJob.java:88)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.xxl.job.core.handler.impl.MethodJobHandler.execute(MethodJobHandler.java:31)
	at com.xxl.job.core.thread.JobThread.run(JobThread.java:166)
Caused by: java.io.IOException: error=2, 没有那个文件或目录
	at java.lang.UNIXProcess.forkAndExec(Native Method)
	at java.lang.UNIXProcess.(UNIXProcess.java:247)
	at java.lang.ProcessImpl.start(ProcessImpl.java:134)
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
	... 7 more

Controller

这里是实际调用Service时的示例代码。

		// 获取cookie. 用户名密码使用默认的
		this.taskService.setCookie(this.taskService.getCookie("http://localhost:8080/xxl-job-admin/login", 
				"admin", "123456"));
		String createUrl = "http://localhost:8080/xxl-job-admin/jobinfo/add";
		// 创建任务
		// 这里homePath是我自定义的一个路径,要求本地可以访问
		// 而且cmd.sh要加上权限,不然会报错
		String cmdStr = homePath + "/cmd.sh";
		int jid = this.taskService.createDynamicJob(createUrl, cmdStr);
		// 要给homePath加权限
		String cmdGrant = "chmod -R 777 " + homePath;
		String[] cmds = new String[] {"sh", "-c", cmdGrant};
		Process pcs = null;
		try {
			pcs = Runtime.getRuntime().exec(cmds);
			BufferedReader stdInput = new BufferedReader(new InputStreamReader(pcs.getInputStream()));
            BufferedReader stdError = new BufferedReader(new InputStreamReader(pcs.getErrorStream()));
            String s = null;
            
            while ((s = stdInput.readLine()) != null) {
                  //log.info(s);
            }
            //log.info("标准错误的输出命令");
            while ((s = stdError.readLine()) != null) {
                  //log.info(s);
            }
			// 会一直等待,所以需要在finally块中杀死进程
			pcs.waitFor();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			//e.printStackTrace();
		} catch (Exception e) {
			//log.error(e.toString());
		}
		finally {
			pcs.destroyForcibly();
		}
		// 触发任务
        this.taskService.triggerDynamicJob("http://localhost:8080/xxl-job-admin/jobinfo/trigger", jid, cmdStr);		
		

成功调度后,调度结果显示成功。如果任务需要的时间较长,那执行结果一开始是null,等任务完成后才会变成成功。
在这里插入图片描述

debug

java.sql.SQLNonTransientConnectionException: Could not create connection to database server

一开始我的xxl-job-admin不是放在docker的,是放在本地的,结果运行时就报这个错误。我也用这篇(docker-配置mysql+外置数据+连接另一个容器(ip法和network法))里的ip法改了admin的配置,仍然报错,应该还是超时的。最后我只能把admin放docker,所幸本地的执行器正常运行。

xxl-job remoting error(No route to host)

在这里插入图片描述
这个是因为9999端口没有开放。先添加端口号,再重载防火墙即可。

firewall-cmd --zone=public --add-port=9999/tcp --permanent
firewall-cmd --reload

Caused by: java.io.IOException: error=2, 没有那个文件或目录

这个要检查2点:

  1. 创建任务时,executorParam或glueSource是不是空的
    如果glueType是GLUE_PYTHON,那么glueSource放的是python ide要运行的语句,为空很可能会报错;如果glueType是BEAN,那么在触发任务时要检查executorParam是不是空的,虽然在创建任务时,executorParam并不是必须带的参数,但是BEAN触发时一定要带。
  2. sh文件是否存在、路径是否可以访问
    尤其是本文这种BEAN模式执行命令的,千万不要在executorParam上写命令啊!!!那里要写sh的文件路径!!!把命令直接写进sh文件,然后填上路径就行,不然会有下面的报错:
2023-09-13 16:57:41 [com.xxl.job.core.thread.JobThread#run]-[133]-[xxl-job, JobThread-17-1694595461226] 
----------- xxl-job job execute start -----------
----------- Param:cd /home/pxy/sgrna && nohup /home/bioinfo/miniconda3/bin/snakemake  -k  --core 8  1>>snakemake.log 2>&1 &
2023-09-13 16:57:41 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[104]-[xxl-job, JobThread-17-1694595461226] java.io.IOException: Cannot run program "cd /xxx/xx && nohup /xxxx &": error=2, 没有那个文件或目录
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
	at com.xxl.job.executor.service.jobhandler.SampleXxlJob.commandJobHandler(SampleXxlJob.java:88)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.xxl.job.core.handler.impl.MethodJobHandler.execute(MethodJobHandler.java:31)
	at com.xxl.job.core.thread.JobThread.run(JobThread.java:166)
Caused by: java.io.IOException: error=2, 没有那个文件或目录
	at java.lang.UNIXProcess.forkAndExec(Native Method)
	at java.lang.UNIXProcess.(UNIXProcess.java:247)
	at java.lang.ProcessImpl.start(ProcessImpl.java:134)
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
	... 7 more

Caused by: java.io.IOException: error=13, 权限不够

这个是因为executorParam填的文件权限不够。

因为我是直接写文件制作的shell文件,默认权限是644,只要改成777之类的就解决问题了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1012543.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

虚拟机批量备份时缩短备份窗口的方法之一:串/并行快照

一条备份任务中是可以同时备份多个虚拟机的&#xff0c;虚拟机在备份的时候&#xff0c;需要对其进行打快照来保证数据的一致性。 对虚拟机进行打快照&#xff0c;需要消耗一定的时间&#xff0c;当虚拟机开启时&#xff0c;虚拟机的内存状态也会被快照下来&#xff0c;因此快…

无涯教程-JavaScript - INDIRECT函数

描述 INDIRECT函数返回由文本字符串指定的引用。 如果您在Excel公式中键入引用B1,则Excel会理解这引用了单元格B1。但是,Excel无法将文本字符串" B1"理解为引用。因此,如果单元格引用采用文本字符串的形式,则需要使用INDIRECT函数将其转换为实际的单元格引用。 立…

SpringMvc---编码过滤器(解决乱码问题)

目录 一、介绍 二、字符编码过滤器 一、介绍 在传递参数时&#xff0c;tomcat8以上能处理get请求的中文乱码&#xff0c;danshibunengqingqiupost请求的中文乱码。 二、字符编码过滤器 对于出现的中文乱码问题&#xff0c;SpringMvc提供了处理中文乱码的过滤器&#xff0c;在…

短视频矩阵系统源码技术独立部署搭建

一、矩阵系统源码主要有三种框架&#xff1a; 矩阵系统源码主要有三种框架&#xff1a;Matplotlib、NumPy和SciPy。Matplotlib是一个用于制图的库&#xff0c;可用于绘制各种类型的图表&#xff0c;包括线图、散点图、柱状图等。NumPy是用于处理大型多维数组和矩阵的库&#x…

Canvas 低代码工具,多人自研开发全流程优化|ModelWhale 版本更新

白露时节、秋雨殷勤&#xff0c;ModelWhale 也迎来了新一轮的版本更新&#xff0c;多层面持续优化你的使用体验。 本次更新中&#xff0c;ModelWhale 主要进行了以下功能迭代&#xff1a; 优化 Canvas 多人自研开发流程&#xff08;团队版✓&#xff09; 新增 Canvas 组件历史…

AIGC 设计能替代真正的设计师设计吗?

AIGC 设计能替代真正的设计师设计吗&#xff1f; 目录 一、写在前面的话 二、AIGC 设计能替代真正的设计师吗&#xff1f; 1.1、传统设计师设计 1.2、AIGC设计 1.3、相关概念 1.4、观点分析 &#xff08;1&#xff09;、审美角度 &#xff08;2&#xff09;、版权角度 …

2023十大杰出外盘黄金交易APP平台最新排名

黄金&#xff0c;作为全球最重要的避险资产之一&#xff0c;一直备受投资者青睐。随着科技的发展&#xff0c;手机炒黄金APP平台逐渐成为投资者的新选择。本文将为您介绍“2023十大杰出外盘黄金交易APP平台最新排名”&#xff0c;帮助您选择合适的平台进行黄金投资。 本次排名…

埃文科技受邀出席“安全堤坝”技术论坛

2023年9月11日&#xff0c;2023年国家网络安全宣传周河南省活动开幕式暨河南省网络文明大会在开封博物馆开幕。由CCF YOCSEF郑州举办的“聚焦数据交易监管技术&#xff0c;筑牢数据交易‘安全堤坝’”技术论坛在开封市博物馆二楼会议厅举行。埃文科技总经理王永博士与副总经理武…

【深度学习】 Python 和 NumPy 系列教程(廿六):Matplotlib详解:3、多子图和布局:subplots()函数

目录 一、前言 二、实验环境 三、Matplotlib详解 1、2d绘图类型 2、3d绘图类型 3、多子图和布局 1. subplot()函数 2. subplots()函数 简单示例 一、前言 Python是一种高级编程语言&#xff0c;由Guido van Rossum于1991年创建。它以简洁、易读的语法而闻名&#xff0…

汽车电子 -- PCAN View 安装与使用

一、PCAN-View 简介 参看&#xff1a;PCAN-View PCAN View 是显示CAN和CAN FD报文的Window软件 PCAN-View 功能概述 PCAN-View for Windows软件是一款简便的CAN监视软件&#xff0c;可用于显示、发送、和记录CAN数据通讯。可手动和定期发送报文&#xff0c;用户可决定比特率…

ZABBIX 6.4官方安装文档

一、官网地址 Zabbix&#xff1a;企业级开源监控解决方案 二、下载 1.选择您Zabbix服务器的平台 2. Install and configure Zabbix for your platform a. Install Zabbix repository # rpm -Uvh https://repo.zabbix.com/zabbix/6.4/rhel/8/x86_64/zabbix-release-6.4-1.el8…

PoeAI:免费使用GPT-4的AI聊天机器人平台

【产品介绍】 • 名称 PoeAI • 成立/上线时间 2023年 • 具体描述 Poe.com是一个提供免费 AI 聊天机器人服务的平台&#xff0c;可以帮助用户解决各种问题&#xff0c;学习新知识&#xff0c;或者只是为了娱乐而聊天。用户可以通过手…

python连接mysql数据库进行增删改查

pymysql是在Python3.x版本中用于连接MySQL服务器的一个库&#xff0c;Python2中则使用mysqldb。 环境准备 python3.7 使用pip安装PyMySQL pip install pymysql先使用第三方工具连接mysql数据库&#xff0c;比如navicat连接mysql 连接名&#xff1a;随便命名 主机名或ip地…

DelayQueue源码分析

底层 DelayQueue 是 JUC 包(java.util.concurrent)为我们提供的延迟队列&#xff0c;用于实现延时任务比如订单下单 15 分钟未支付直接取消。它是 BlockingQueue 的一种&#xff0c;底层是一个基于 PriorityQueue 实现的一个无界队列&#xff0c;是线程安全的。默认情况下, De…

UG\NX二次开发 二维向量相加

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG\NX二次开发 二维向量相加 效果: 代码: #include "me.hpp"void doIt() {const double vec1[2] = { 1.0,2.0 };const double vec2[2] = { 2.0,2.…

高效成绩查询系统助力,让学校管理事半功倍

各位老师们&#xff0c;大家好&#xff01;作为教育工作者&#xff0c;我们都了解成绩查询在学校管理中的重要性。然而&#xff0c;传统的查询方式往往繁琐耗时&#xff0c;给我们带来了不少困扰。因此&#xff0c;今天我将向大家介绍一个极其便捷的查询工具&#xff0c;能够帮…

VR云游:让游客足不出户享受旅行的乐趣

随着人们的生活水平不断提高&#xff0c;对于旅行的需求也在日益增长&#xff0c;既要玩的舒心&#xff0c;也要享受的舒服&#xff0c;因此VR全景云游就成为了一种新型的旅行方式&#xff0c;人们足不出户就可以沉浸式游览各地自然风光与名胜古迹。 VR云游景区是一种全新的旅游…

反渗透,sql注入漏洞扫描工具

工具一:zap 下载地址&#xff1a;ZAP GitHub OWASP Zed 攻击代理&#xff08;ZAP&#xff09;是世界上最受欢迎的免费安全审计工具之一&#xff0c;由数百名国际志愿者积极维护。它可以帮助你在开发和测试应用程序时自动查找 Web 应用程序中的安全漏洞。可以说 ZAP 是一个中…

百货店失去核心竞争力了吗?全靠超市即时零售撑起

近年来&#xff0c;传统百货不景气&#xff0c;不过&#xff0c;从今年上半年的情况看&#xff0c;似乎有些好转。 然而&#xff0c;实际情况并不如预期那么好&#xff0c;有专家认为&#xff1a;“百货上市公司业绩和去年相比增长是正常的。实际上&#xff0c;百货业态增长的…

陪诊系统|陪诊软件为用户提供多元化的医疗服务

陪诊小程序作为一种人性化的医疗工具&#xff0c;具备多种功能。首先&#xff0c;它可以预约挂号。患者只需通过简单的操作&#xff0c;即可轻松选择合适的医生和挂号时间&#xff0c;免去了排队等待的繁琐过程。其次&#xff0c;陪诊小程序为患者提供了在线问诊的渠道。通过平…