diff --git a/back/api/cron.ts b/back/api/cron.ts index 2dc7e5f2..cd365132 100644 --- a/back/api/cron.ts +++ b/back/api/cron.ts @@ -177,6 +177,8 @@ export default (app: Router) => { labels: Joi.array().optional(), sub_id: Joi.number().optional().allow(null), extra_schedules: Joi.array().optional().allow(null), + task_before: Joi.string().optional().allow('').allow(null), + task_after: Joi.string().optional().allow('').allow(null), }), }), async (req: Request, res: Response, next: NextFunction) => { @@ -335,6 +337,8 @@ export default (app: Router) => { name: Joi.string().optional().allow(null), sub_id: Joi.number().optional().allow(null), extra_schedules: Joi.array().optional().allow(null), + task_before: Joi.string().optional().allow('').allow(null), + task_after: Joi.string().optional().allow('').allow(null), id: Joi.number().required(), }), }), diff --git a/back/data/cron.ts b/back/data/cron.ts index 67a57c95..b234d59c 100644 --- a/back/data/cron.ts +++ b/back/data/cron.ts @@ -19,6 +19,8 @@ export class Crontab { last_execution_time?: number; sub_id?: number; extra_schedules?: Array<{ schedule: string }>; + task_before?: string; + task_after?: string; constructor(options: Crontab) { this.name = options.name; @@ -41,6 +43,8 @@ export class Crontab { this.last_execution_time = options.last_execution_time || 0; this.sub_id = options.sub_id; this.extra_schedules = options.extra_schedules; + this.task_before = options.task_before; + this.task_after = options.task_after; } } @@ -77,5 +81,7 @@ export const CrontabModel = sequelize.define('Crontab', { last_running_time: DataTypes.NUMBER, last_execution_time: DataTypes.NUMBER, sub_id: { type: DataTypes.NUMBER, allowNull: true }, - extra_schedules: DataTypes.JSON + extra_schedules: DataTypes.JSON, + task_before: DataTypes.STRING, + task_after: DataTypes.STRING, }); diff --git a/back/loaders/db.ts b/back/loaders/db.ts index 63a6d500..c650d654 100644 --- a/back/loaders/db.ts +++ b/back/loaders/db.ts @@ -52,6 +52,12 @@ export default async () => { try { await sequelize.query('alter table Crontabs add column extra_schedules JSON'); } catch (error) { } + try { + await sequelize.query('alter table Crontabs add column task_before TEXT'); + } catch (error) { } + try { + await sequelize.query('alter table Crontabs add column task_after TEXT'); + } catch (error) { } // 2.10-2.11 升级 const cronDbFile = path.join(config.rootPath, 'db/crontab.db'); diff --git a/back/schedule/addCron.ts b/back/schedule/addCron.ts index 1b123568..e5289c1d 100644 --- a/back/schedule/addCron.ts +++ b/back/schedule/addCron.ts @@ -16,11 +16,6 @@ const addCron = ( scheduleStacks.get(id)?.forEach((x) => x.cancel()); } - let cmdStr = command.trim(); - if (!cmdStr.startsWith(TASK_PREFIX) && !cmdStr.startsWith(QL_PREFIX)) { - cmdStr = `${TASK_PREFIX}${cmdStr}`; - } - Logger.info( '[schedule][创建定时任务], 任务ID: %s, cron: %s, 执行命令: %s', id, @@ -41,14 +36,14 @@ const addCron = ( scheduleStacks.set(id, [ nodeSchedule.scheduleJob(id, schedule, async () => { - Logger.info(`[schedule][准备运行任务] 命令: ${cmdStr}`); - runCron(`ID=${id} ${cmdStr}`); + Logger.info(`[schedule][准备运行任务] 命令: ${command}`); + runCron(command); }), ...(extraSchedules?.length ? extraSchedules.map((x) => nodeSchedule.scheduleJob(id, x.schedule, async () => { - Logger.info(`[schedule][准备运行任务] 命令: ${cmdStr}`); - runCron(`ID=${id} ${cmdStr}`); + Logger.info(`[schedule][准备运行任务] 命令: ${command}`); + runCron(command); }), ) : []), diff --git a/back/services/cron.ts b/back/services/cron.ts index 9f5ad8d0..77abcf43 100644 --- a/back/services/cron.ts +++ b/back/services/cron.ts @@ -33,7 +33,7 @@ export default class CronService { const doc = await this.insert(tab); if (this.isSixCron(doc) || doc.extra_schedules?.length) { await cronClient.addCron([ - { id: String(doc.id), schedule: doc.schedule!, command: doc.command, extraSchedules: doc.extra_schedules || [] }, + { id: String(doc.id), schedule: doc.schedule!, command: this.makeCommand(doc), extraSchedules: doc.extra_schedules || [] }, ]); } await this.set_crontab(); @@ -60,7 +60,7 @@ export default class CronService { { id: String(newDoc.id), schedule: newDoc.schedule!, - command: newDoc.command, + command: this.makeCommand(newDoc), extraSchedules: newDoc.extra_schedules || [] }, ]); @@ -406,21 +406,7 @@ export default class CronService { this.logger.silly('ID: ' + id); this.logger.silly('Original command: ' + command); - let cmdStr = command; - if (!cmdStr.startsWith(TASK_PREFIX) && !cmdStr.startsWith(QL_PREFIX)) { - cmdStr = `${TASK_PREFIX}${cmdStr}`; - } - if ( - cmdStr.endsWith('.js') || - cmdStr.endsWith('.py') || - cmdStr.endsWith('.pyc') || - cmdStr.endsWith('.sh') || - cmdStr.endsWith('.ts') - ) { - cmdStr = `${cmdStr} now`; - } - - const cp = spawn(`real_log_path=${logPath} ID=${id} ${cmdStr}`, { shell: '/bin/bash' }); + const cp = spawn(`real_log_path=${logPath} no_delay=true ${this.makeCommand(cron)}`, { shell: '/bin/bash' }); await CrontabModel.update( { status: CrontabStatus.running, pid: cp.pid, log_path: logPath }, @@ -507,12 +493,22 @@ export default class CronService { } } - private make_command(tab: Crontab) { + private makeCommand(tab: Crontab) { let command = tab.command.trim(); if (!command.startsWith(TASK_PREFIX) && !command.startsWith(QL_PREFIX)) { command = `${TASK_PREFIX}${tab.command}`; } - const crontab_job_string = `ID=${tab.id} ${command}`; + let commandVariable = `ID=${tab.id} ` + if (tab.task_before) { + commandVariable += `task_before='${tab.task_before.replace(/'/g, "'\\''") + .trim()}' `; + } + if (tab.task_after) { + commandVariable += `task_after='${tab.task_after.replace(/'/g, "'\\''") + .trim()}' `; + } + + const crontab_job_string = `${commandVariable}${command}`; return crontab_job_string; } @@ -525,12 +521,12 @@ export default class CronService { crontab_string += '# '; crontab_string += tab.schedule; crontab_string += ' '; - crontab_string += this.make_command(tab); + crontab_string += this.makeCommand(tab); crontab_string += '\n'; } else { crontab_string += tab.schedule; crontab_string += ' '; - crontab_string += this.make_command(tab); + crontab_string += this.makeCommand(tab); crontab_string += '\n'; } }); @@ -584,7 +580,7 @@ export default class CronService { .map((doc) => ({ id: String(doc.id), schedule: doc.schedule!, - command: doc.command, + command: this.makeCommand(doc), extraSchedules: doc.extra_schedules || [] })); await cronClient.addCron(sixCron); diff --git a/shell/otask.sh b/shell/otask.sh index 72166ad4..e573c504 100755 --- a/shell/otask.sh +++ b/shell/otask.sh @@ -94,7 +94,7 @@ env_str_to_array() { ## 正常运行单个脚本,$1:传入参数 run_normal() { local file_param=$1 - if [[ $# -eq 1 ]] && [[ "$real_time" != "true" ]]; then + if [[ $# -eq 1 ]] && [[ "$real_time" != "true" ]] && [[ "$no_delay" != "true" ]]; then random_delay "$file_param" fi diff --git a/shell/share.sh b/shell/share.sh index c879dd81..aab2cb1c 100755 --- a/shell/share.sh +++ b/shell/share.sh @@ -436,11 +436,23 @@ handle_task_before() { [[ $is_macos -eq 0 ]] && check_server . $file_task_before "$@" + + if [[ $task_before ]]; then + echo -e "执行前置命令\n" + eval "$task_before" + echo -e "\n执行前置命令结束\n" + fi } handle_task_after() { . $file_task_after "$@" + if [[ $task_after ]]; then + echo -e "\n执行后置命令\n" + eval "$task_after" + echo -e "\n执行后置命令结束" + fi + local etime=$(date "+$time_format") local end_time=$(format_time "$time_format" "$etime") local end_timestamp=$(format_timestamp "$time_format" "$etime") diff --git a/src/locales/en-US.json b/src/locales/en-US.json index ad3352ca..3fc2f8c6 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -456,5 +456,9 @@ "语言": "Language", "中...": "ing...", "请选择操作符": "Please select operator", - "新增定时规则": "New Timing Rules" + "新增定时规则": "Add Timing Rules", + "运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands before executing the task, e.g., cp/mv/python3 xxx.py/node xxx.js", + "运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands after executing the task, e.g., cp/mv/python3 xxx.py/node xxx.js", + "请输入运行任务前要执行的命令": "Please enter the command to run before executing the task", + "请输入运行任务后要执行的命令": "Please enter the command to run after executing the task" } diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json index d59b8bbd..65d85d14 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -456,5 +456,9 @@ "语言": "语言", "中...": "中...", "请选择操作符": "请选择操作符", - "新增定时规则": "新增定时规则" + "新增定时规则": "新增定时规则", + "运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", + "运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", + "请输入运行任务前要执行的命令": "请输入运行任务前要执行的命令", + "请输入运行任务后要执行的命令": "请输入运行任务后要执行的命令" } diff --git a/src/pages/crontab/index.tsx b/src/pages/crontab/index.tsx index de3310cd..7423c4f6 100644 --- a/src/pages/crontab/index.tsx +++ b/src/pages/crontab/index.tsx @@ -43,7 +43,6 @@ import { request } from '@/utils/http'; import CronModal, { CronLabelModal } from './modal'; import CronLogModal from './logModal'; import CronDetailModal from './detail'; -import cron_parser from 'cron-parser'; import { diffTime } from '@/utils/date'; import { history, useOutletContext } from '@umijs/max'; import './index.less'; diff --git a/src/pages/crontab/modal.tsx b/src/pages/crontab/modal.tsx index 1bee2419..1a5e259a 100644 --- a/src/pages/crontab/modal.tsx +++ b/src/pages/crontab/modal.tsx @@ -143,6 +143,32 @@ const CronModal = ({ + + + + + + );