定时任务增加 work_dir 设置

This commit is contained in:
whyour 2026-06-07 13:19:01 +08:00
parent 865e3035b9
commit fd6b4e4cde
5 changed files with 82 additions and 2 deletions

View File

@ -23,6 +23,7 @@ export class Crontab {
task_after?: string; task_after?: string;
log_name?: string; log_name?: string;
allow_multiple_instances?: 1 | 0; allow_multiple_instances?: 1 | 0;
work_dir?: string;
constructor(options: Crontab) { constructor(options: Crontab) {
this.name = options.name; this.name = options.name;
@ -49,6 +50,7 @@ export class Crontab {
this.task_after = options.task_after; this.task_after = options.task_after;
this.log_name = options.log_name; this.log_name = options.log_name;
this.allow_multiple_instances = options.allow_multiple_instances || 0; this.allow_multiple_instances = options.allow_multiple_instances || 0;
this.work_dir = options.work_dir;
} }
} }
@ -90,4 +92,5 @@ export const CrontabModel = sequelize.define<CronInstance>('Crontab', {
task_after: DataTypes.STRING, task_after: DataTypes.STRING,
log_name: DataTypes.STRING, log_name: DataTypes.STRING,
allow_multiple_instances: DataTypes.NUMBER, allow_multiple_instances: DataTypes.NUMBER,
work_dir: DataTypes.STRING,
}); });

View File

@ -41,6 +41,7 @@ export default async () => {
column: 'allow_multiple_instances', column: 'allow_multiple_instances',
type: 'NUMBER', type: 'NUMBER',
}, },
{ table: 'Crontabs', column: 'work_dir', type: 'VARCHAR(255)' },
{ table: 'Envs', column: 'isPinned', type: 'NUMBER' }, { table: 'Envs', column: 'isPinned', type: 'NUMBER' },
{ table: 'Envs', column: 'labels', type: 'JSON' }, { table: 'Envs', column: 'labels', type: 'JSON' },
]; ];

View File

@ -678,6 +678,9 @@ export default class CronService {
.replace(/;? *\n/g, ';') .replace(/;? *\n/g, ';')
.trim()}' `; .trim()}' `;
} }
if (tab.work_dir) {
commandVariable += `work_dir='${tab.work_dir.replace(/'/g, "'\\''")}' `;
}
const crontab_job_string = `${commandVariable}${command}`; const crontab_job_string = `${commandVariable}${command}`;
return crontab_job_string; return crontab_job_string;

View File

@ -96,6 +96,26 @@ append_node_dependency_path() {
enter_script_workdir() { enter_script_workdir() {
local use_dot_prefix="$1" local use_dot_prefix="$1"
# 如果定时任务显式指定了工作目录,优先使用
if [[ -n "${work_dir:=}" ]]; then
if [[ "${work_dir}" == /* ]]; then
cd "${work_dir}"
else
cd "${dir_scripts}/${work_dir}"
fi
# 仍然处理 file_param 中的路径前缀,确保命令路径正确
if [[ ${file_param} =~ "/" ]]; then
local script_name="${file_param##*/}"
if [[ "${use_dot_prefix}" == "true" ]]; then
file_param="./${script_name}"
else
file_param="${script_name}"
fi
fi
return
fi
# 自动检测:从 file_param 中提取脚本所在目录
cd $dir_scripts cd $dir_scripts
if [[ ${file_param} =~ "/" ]]; then if [[ ${file_param} =~ "/" ]]; then
local script_dir="${file_param%/*}" local script_dir="${file_param%/*}"
@ -210,9 +230,53 @@ run_designated() {
run_else() { run_else() {
local file_param="$1" local file_param="$1"
enter_script_workdir true # 判断 file_param 本身是否是脚本文件
local is_file_script="false"
if [[ "$file_param" == *.js || "$file_param" == *.mjs ||
"$file_param" == *.py || "$file_param" == *.pyc ||
"$file_param" == *.sh || "$file_param" == *.ts ]]; then
is_file_script="true"
fi
shift if [[ "$is_file_script" != "true" ]]; then
# file_param 不是脚本,从后续参数中查找脚本路径来确定工作目录
local script_for_dir=""
for arg in "$@"; do
if [[ "$arg" == *.js || "$arg" == *.mjs ||
"$arg" == *.py || "$arg" == *.pyc ||
"$arg" == *.sh || "$arg" == *.ts ]]; then
script_for_dir="$arg"
break
fi
done
if [[ -n "$script_for_dir" ]]; then
local saved_file_param="$file_param"
file_param="$script_for_dir"
enter_script_workdir true
local adjusted_script="$file_param"
file_param="$saved_file_param"
shift
local new_args=()
for arg in "$@"; do
if [[ "$arg" == "$script_for_dir" ]]; then
new_args+=("$adjusted_script")
else
new_args+=("$arg")
fi
done
set -- "${new_args[@]}"
else
# 没有找到脚本参数,只 cd 到 scripts 目录
enter_script_workdir true
shift
fi
else
# file_param 本身就是脚本,直接用 enter_script_workdir 处理
enter_script_workdir true
shift
fi
clear_non_sh_env clear_non_sh_env
$timeoutCmd $which_program $file_param "$@" $timeoutCmd $which_program $file_param "$@"

View File

@ -229,6 +229,15 @@ const CronModal = ({
maxLength={200} maxLength={200}
/> />
</Form.Item> </Form.Item>
<Form.Item
name="work_dir"
label={intl.get('工作目录')}
tooltip={intl.get(
'脚本执行时的工作目录,留空则自动检测。相对路径基于 scripts 目录,也支持绝对路径',
)}
>
<Input placeholder={intl.get('留空自动检测,或输入相对/绝对路径')} />
</Form.Item>
<Form.Item <Form.Item
name="task_before" name="task_before"
label={intl.get('执行前')} label={intl.get('执行前')}