环境配置
假设目前已配置好如下环境:
Windows:JDK、Git、IDEA、Maven、Python
Linux:JDK、Kettle
gitee仓库地址
https://gitee.com/xuxueli0323/xxl-job
克隆仓库
shell
# 默认克隆最新版本,只支持jdk17
git clone https://gitee.com/xuxueli0323/xxl-job.git
# 指定克隆版本,2.5.0支持jdk8
git clone -b 2.5.0 https://gitee.com/xuxueli0323/xxl-job.git
执行sql文件
克隆项目后,找到xxl-job\doc\db\tables_xxl_job.sql,在数据库执行即可。
注:目前xxl-job 2.5.0版的
tables_xxl_job.sql是mysql语法,若需要支持其他数据库,需要自己改一下sql文件语法,并且在项目pom.xml中引入其他数据库的驱动等。
修改配置
调度中心和执行器说明
xxl-job分调度中心和执行器,其中对比说明如下表:
| 对比维度 | 调度中心 (Admin) | 执行器 (Executor) |
|---|---|---|
| 核心角色 | 调度大脑 - 任务调度指挥中心 | 执行终端 - 任务具体执行节点 |
| 主要职责 | 1. 任务调度决策 2. 任务管理(增删改查) 3. 调度触发 4. 执行器管理 5. 日志监控 | 1. 任务实际执行 2. 业务逻辑处理 3. 心跳注册 4. 执行结果反馈 |
| 功能定位 | 管理控制层 - 负责"何时执行"和"分配给谁" | 业务执行层 - 负责"如何执行" |
| 部署方式 | 独立部署,通常一个项目只需一个调度中心(支持集群) | 集成部署,每个需要执行任务的服务都需部署执行器 |
| 数据存储 | 依赖数据库(MySQL等),存储任务配置、日志等 | 不依赖数据库(除非业务需要),本地内存运行 |
| 通信方向 | 主动调用 → 向执行器发送调度请求 | 被动响应 ← 接收调度请求并返回结果 |
| 集群模式 | 中心化集群:多个调度中心实例共用同一个数据库,通过数据库锁避免重复调度 | 分布式集群:多个执行器实例注册到同一个调度中心,负载均衡执行任务 |
| 典型配置 | 端口:8080(默认) 数据库:MySQL Web界面:提供管理控制台 | 端口:9999(默认) AppName:执行器名称(唯一标识) 注册地址:自动/手动注册 |
| 工作流程 | 1. 解析任务Cron表达式 2. 到达触发时间 3. 选择合适的执行器 4. 发送HTTP请求调用任务 5. 记录执行日志 | 1. 启动时向调度中心注册 2. 接收调度请求 3. 通过反射调用本地JobHandler 4. 执行业务代码 5. 返回执行结果 |
| 关键配置 | spring.datasource.url spring.datasource.username spring.datasource.password spring.datasource.driver-class-name xxl.job.accessToken xxl.job.i18n | xxl.job.admin.addresses xxl.job.admin.accessToken xxl.job.executor.appname xxl.job.executor.port |
调度中心
目前演示克隆的是xxl-job 2.5.0版本,并且数据库也是mysql。
使用IDEA打开xxl-job项目,打开xxl-job-admin/src/main/resources/application.properties,如下,需修改数据库配置信息等。
properties
### web【启动端口】
server.port=8080
server.servlet.context-path=/xxl-job-admin
### actuator
management.server.base-path=/actuator
management.health.mail.enabled=false
### resources
spring.mvc.servlet.load-on-startup=0
spring.mvc.static-path-pattern=/static/**
spring.web.resources.static-locations=classpath:/static/
### freemarker
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8
spring.freemarker.request-context-attribute=request
spring.freemarker.settings.number_format=0.##########
spring.freemarker.settings.new_builtin_class_resolver=safer
### mybatis
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml
### datasource-pool
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=HikariCP
spring.datasource.hikari.max-lifetime=900000
spring.datasource.hikari.connection-timeout=10000
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.validation-timeout=1000
### xxl-job, datasource【必须修改,需自行手动修改】
spring.datasource.url=jdbc:mysql://192.168.88.199:3306/xxl_job_8?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
### xxl-job, email【可选,配置邮箱发送地址】
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=xxx@qq.com
spring.mail.from=xxx@qq.com
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
### xxl-job, access token【可选,默认token,需与执行器的保持一致】
xxl.job.accessToken=default_token
### xxl-job, access token
xxl.job.timeout=3
### xxl-job, i18n (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en")【可选,默认语言是简体中文,zh_TC:繁体中文,en:英文】【或者通过启动的时候进行指定】
xxl.job.i18n=zh_CN
## xxl-job, triggerpool max size
# 快速线程池的最大线程数,默认为200。
xxl.job.triggerpool.fast.max=200
# 慢速线程池的最大线程数,默认为100
xxl.job.triggerpool.slow.max=100
### xxl-job, log retention days
# 日志默认过期天数
xxl.job.logretentiondays=30
至少要修改
### xxl-job, datasource的数据库连接信息,也就是执行sql文件的数据库信息。
执行器
打开xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties,需修改如下配置信息等。
properties
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"【指定部署调度中心的地址,比如将调度中心部署在192.168.88.199这台服务器】
xxl.job.admin.addresses=http://192.168.88.199:8080/xxl-job-admin
### xxl-job, access token【可选,默认token,需与调度中心的保持一致】
xxl.job.admin.accessToken=default_token
修改完配置后,可以直接在IDEA分别启动调度中心和执行器查看是否正常,即xxl-job-admin/src/main/java/com/xxl/job/admin/XxlJobAdminApplication.java和xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/XxlJobExecutorApplication.java
使用Maven进行打包
因为后期在服务器上进行部署是执行jar包的方式,故以上配置完,即可进行打包,直接在IDEA中进行打包。

或者在终端输入
mvn package命令来进行打包。
打包完成后,找到打包的jar包,分两个,一个是调度中心,一个是执行器


部署服务
因为目前需要进行搭建服务,计划将调度中心部署在Linux服务器上,执行器在Linux和Windows上各自部署一个。
| 说明 | IP地址 |
|---|---|
| 调度中心IP | 192.168.88.199 |
| 执行器IP(Linux) | 192.168.88.199 |
| 执行器IP(Windows) | 10.181.176.27 |
注:执行器可配置一到多个,看自己需求。
将jar包使用FinalShell上传到Linux,

启动服务
Linux上需要进行启动调度中心和执行器,采用后台运行。
shell
cd /usr/local/xxl-job
# 1. 启动调度中心
nohup java -jar xxl-job-admin-2.5.0.jar > admin.log 2>&1 &
# 1. 启动调度中心(或指定显示语言为繁体中文)
# nohup java -jar xxl-job-admin-2.5.0.jar --xxl.job.i18n=zh_TC > admin.log 2>&1 &
# 2. 启动执行器
nohup java -jar xxl-job-executor-sample-springboot-2.5.0.jar > executor.log 2>&1 &
# 若8080端口未开放,则进行如下处理
# 查看开放的端口:
firewall-cmd --zone=public --list-ports
# 开放指定端口:
firewall-cmd --zone=public --add-port=8080/tcp --permanent
# 立即生效:
firewall-cmd --reload

Windows需进行启动执行器,同样采用后台运行。
进入xxl-job-executor-samples\xxl-job-executor-sample-springboot\target目录下,打开PowerShell,直接执行如下命令:
powershell
# 在PowerShell中运行
Start-Process -WindowStyle Hidden -FilePath "java" -ArgumentList "-jar xxl-job-executor-sample-springboot-2.5.0.jar" -RedirectStandardOutput "executor.log" -RedirectStandardError "error.log"

关闭服务
Linux关闭调度中心和执行器
shell
# 查看进程(精确过滤)
ps -ef | grep xxl-job
# 强制结束
kill -9 进程ID

Windows关闭执行器
powershell
# 在PowerShell中运行,查看进程ID
Get-CimInstance Win32_Process -Filter "name='java.exe'" | Where-Object { $_.CommandLine -like "*xxl-job-executor-sample-springboot-2.5.0.jar*" }
# 强制结束
Stop-Process -Id 进程ID -Force

管理控制台
以上启动服务器后,即可进入管理控制台,在本地浏览器访问http://192.168.88.199:8080/xxl-job-admin/toLogin
默认账号:admin
默认密码:123456

ip地址为启动
调度中心所在服务器地址
点击登录即可查看

注:以上
运行报表信息为之前配置的,若第一次使用,则此处相关数据为空。
配置执行器
登录管理控制台后,第一步就是配置执行地址,因为部署了2个执行器,故此处需要进行配置。
点击【新增】

同理再新增一个windows的执行器,

2个执行器均配置完成如下:

任务管理
Linux执行器相关任务
为测试功能是否正常,点击任务管理->新增,此处测试运行模式为GLUE(Shell)是否正常,点击保存。

点击操作的GLUE IDE,进行编辑

注:默认新增任务的状态是STOP ,若需要使CRON表达式生效来定时执行任务的话需要点击操作的启动使其变为RUNNING;若只想运行一次,则点击操作的执行一次即可。
Shell脚本如下:

进行保存即可。
测试为使用xxl-job的Linux执行器通过Shell来执行kettle-job,以上是局部Shell脚本,完整脚本在下文
Windows执行器相关任务
同理,点击任务管理->新增,此处测试运行模式为GLUE(PowerShell)是否正常,点击保存。

同理,点击操作的GLUE IDE,进行编辑

再新增运行模式为GLUE(Python)任务,点击保存。

同理,点击操作的GLUE IDE,进行编辑

测试为使用xxl-job的Windows执行器通过PowerShell或Python来执行exe,以上是局部脚本,完整脚本在下文。
任务类型为
GLUE(PowerShell)会存在中文乱码情况:执行程式路径若存在中文则会找不到,并且输出的内容也会乱码,故此处测试需将脚本改为纯英文;任务类型为
GLUE(Python)来解决中文乱码情况:执行程式路径若存在中文正常执行,并且输出的内容也正常显示。
调度日志
任务配置完成后,点击三个任务的操作->执行一次即可启动执行一次任务。启动后,点击调度日志即可查看任务执行结果。
Linux执行器任务调度日志
查看执行结果:

点击操作->执行日志查看具体日志:

kettle-job功能是往目标表插入数据,为测试xxl-job的失败重试机制,故该目标表进行删除,所以执行结果一定会失败,从而测试重试机制,如下重试了一次,同样失败。

现在恢复创建该目标表,再次点击执行一次任务,查看调度日志:

查看执行日志:

Windows执行器任务调度日志
查看执行结果:

执行该exe是会显示一个时间弹窗:

点击操作->执行日志查看具体日志:

同理查看运行模式为GLUE(Python)任务的执行日志:

使用Python来执行exe,能解决中文乱码问题
执行状态说明
在xxl-job中,判断任务执行是否成功的标准如下,故下文的所有脚本均可以针对该规则来实现失败重试机制。
shell
# 0代表成功,非0代表失败,若失败会触发xxl-job的自动失败重试
exit 0
执行Kettle
执行作业脚本
shell
#!/bin/bash
source /etc/profile
KETTLE_HOME=/usr/local/kettle/data-integration
KETTLE_LOG=/usr/local/kettle/kettle_run_log
UPDATE=$(date "+%F-%H-%M-%S")
JOBNAME="job1"
# 定义完整的日志文件路径
LOG_FILE="$KETTLE_LOG/${UPDATE}_$JOBNAME.log"
# 确保日志目录存在
mkdir -p "$KETTLE_LOG"
# 执行 Kettle 作业并捕获退出码
# 注意:使用子shell来执行,这样可以捕获整个管道的退出状态
set -o pipefail # 确保管道中任意命令失败都返回非0
# 执行 Kettle 并记录日志
bash "$KETTLE_HOME/kitchen.sh" \
-rep=repo_ssh \
-user=admin \
-pass=admin \
-dir=/ETL \
-job="$JOBNAME" \
-level=Detailed 2>&1 | tee "$LOG_FILE"
# 获取退出状态
EXIT_CODE=$?
echo "Kettle 退出代码: $EXIT_CODE"
echo "日志文件: $LOG_FILE"
# 检查日志中是否包含 ERROR(忽略大小写)
if grep -qi "ERROR" "$LOG_FILE"; then
echo "⚠️ 警告:Kettle日志中发现 ERROR 关键字!"
# 显示部分错误日志
echo "=== 发现的错误日志片段 ==="
grep -i "ERROR" "$LOG_FILE" | head -10
exit 1
# 再检查退出代码,若不等于0则判定失败
elif [ $EXIT_CODE -ne 0 ]; then
echo "❌ Kettle 执行失败,退出码: $EXIT_CODE"
exit $EXIT_CODE
else
echo "✅ 未发现 ERROR,任务成功"
exit 0
fi
执行转换脚本
shell
#!/bin/bash
source /etc/profile
KETTLE_HOME=/usr/local/kettle/data-integration
KETTLE_LOG=/usr/local/kettle/kettle_run_log
UPDATE=$(date "+%F-%H-%M-%S")
TRANSNAME="trans1"
# 定义完整的日志文件路径
LOG_FILE="$KETTLE_LOG/${UPDATE}_$TRANSNAME.log"
# 确保日志目录存在
mkdir -p "$KETTLE_LOG"
# 执行 Kettle 作业并捕获退出码
# 注意:使用子shell来执行,这样可以捕获整个管道的退出状态
set -o pipefail # 确保管道中任意命令失败都返回非0
# 执行 Kettle 并记录日志
bash "$KETTLE_HOME/pan.sh" \
-rep=repo_ssh \
-user=admin \
-pass=admin \
-dir=/ETL \
-trans="$TRANSNAME" \
-level=Detailed 2>&1 | tee "$LOG_FILE"
# 获取退出状态
EXIT_CODE=$?
echo "Kettle 退出代码: $EXIT_CODE"
echo "日志文件: $LOG_FILE"
# 检查日志中是否包含 ERROR(忽略大小写)
if grep -qi "ERROR" "$LOG_FILE"; then
echo "⚠️ 警告:Kettle日志中发现 ERROR 关键字!"
# 显示部分错误日志
echo "=== 发现的错误日志片段 ==="
grep -i "ERROR" "$LOG_FILE" | head -10
exit 1
# 再检查退出代码,若不等于0则判定失败
elif [ $EXIT_CODE -ne 0 ]; then
echo "❌ Kettle 执行失败,退出码: $EXIT_CODE"
exit $EXIT_CODE
else
echo "✅ 未发现 ERROR,任务成功"
exit 0
fi
执行EXE脚本
使用PowerShell
因为xxl-job执行Powershell脚本会导致中文乱码,故目前修改为全英文。
Powershell脚本:
powershell
# PowerShell script for XXL-Job
# Change to $true if administrator privileges are required
$UseAdmin = $false
$exePath = "C:\Users\Aiw\Desktop\py-exe\dist\time_popup2.exe"
# Check if the executable file exists
if (!(Test-Path $exePath)) {
Write-Output "Error: Program file not found"
exit 1
}
try {
if ($UseAdmin) {
Write-Output "Executing with administrator privileges..."
$process = Start-Process powershell.exe -ArgumentList "-Command", "Start-Process '$exePath' -Wait; exit `$LASTEXITCODE" -Verb RunAs -Wait -PassThru
} else {
Write-Output "Executing with normal privileges..."
$process = Start-Process -FilePath $exePath -Wait -PassThru -NoNewWindow
}
Write-Output "Execution completed, exit code: $($process.ExitCode)"
exit $process.ExitCode
} catch {
Write-Output "Execution failed: $_"
exit 1
}
使用Pythhon
使用Python来解决xxl-job执行Powershell脚本导致中文乱码问题,支持中文路径并且中文输出。
python
#!/usr/bin/env python3
import os
import subprocess
import sys
# 是否使用管理员权限
USE_ADMIN = False
# 执行的程式路径
EXE_PATH = r"C:\Users\Aiw\Desktop\py-exe中文路径测试\dist\time_popup2.exe"
# 设置输出编码为utf-8
sys.stdout.reconfigure(encoding='utf-8')
# 主逻辑
print(f"程式文件: {EXE_PATH}")
if not os.path.exists(EXE_PATH):
print("错误: 程式文件不存在!")
sys.exit(1)
try:
if USE_ADMIN:
print("使用管理员权限执行。")
cmd = f'Start-Process "{EXE_PATH}" -Verb RunAs -Wait'
result = subprocess.run(["powershell", "-Command", cmd],
capture_output=True, text=True, encoding='gbk')
else:
print("使用普通权限执行。")
result = subprocess.run([EXE_PATH],
capture_output=True, text=True, encoding='gbk')
print(f"执行完成,退出码: {result.returncode}")
# 直接返回程序的退出码
sys.exit(result.returncode)
except Exception as e:
print(f"执行失败: {e}")
sys.exit(1)