mirror of
https://github.com/whyour/qinglong.git
synced 2026-07-17 09:34:31 +08:00
定时任务支持自定义日志文件或者 /dev/null (#2823)
* Initial plan * Add log_name field to enable custom log folder naming Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Add database migration for log_name column Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Add security validation to prevent path traversal attacks Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Apply prettier formatting to modified files Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Support absolute paths like /dev/null for log redirection Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Restrict absolute paths to log directory except /dev/null Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
This commit is contained in:
+10
-1
@@ -521,5 +521,14 @@
|
||||
"远程仓库缓存": "Remote repository cache",
|
||||
"SSH 文件缓存": "SSH file cache",
|
||||
"清除依赖缓存": "Clean dependency cache",
|
||||
"清除成功": "Clean successful"
|
||||
"清除成功": "Clean successful",
|
||||
"日志名称": "Log Name",
|
||||
"自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成": "Custom log folder name to distinguish logs from different tasks. Leave blank to auto-generate",
|
||||
"自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持绝对路径如 /dev/null": "Custom log folder name to distinguish logs from different tasks. Leave blank to auto-generate. Supports absolute paths like /dev/null",
|
||||
"自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内": "Custom log folder name to distinguish logs from different tasks. Leave blank to auto-generate. Supports /dev/null to discard logs, other absolute paths must be within log directory",
|
||||
"请输入自定义日志文件夹名称": "Please enter a custom log folder name",
|
||||
"请输入自定义日志文件夹名称或绝对路径": "Please enter a custom log folder name or absolute path",
|
||||
"请输入自定义日志文件夹名称或 /dev/null": "Please enter a custom log folder name or /dev/null",
|
||||
"日志名称只能包含字母、数字、下划线和连字符": "Log name can only contain letters, numbers, underscores and hyphens",
|
||||
"日志名称不能超过100个字符": "Log name cannot exceed 100 characters"
|
||||
}
|
||||
|
||||
+10
-1
@@ -521,5 +521,14 @@
|
||||
"远程仓库缓存": "远程仓库缓存",
|
||||
"SSH 文件缓存": "SSH 文件缓存",
|
||||
"清除依赖缓存": "清除依赖缓存",
|
||||
"清除成功": "清除成功"
|
||||
"清除成功": "清除成功",
|
||||
"日志名称": "日志名称",
|
||||
"自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成": "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成",
|
||||
"自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持绝对路径如 /dev/null": "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持绝对路径如 /dev/null",
|
||||
"自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内": "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内",
|
||||
"请输入自定义日志文件夹名称": "请输入自定义日志文件夹名称",
|
||||
"请输入自定义日志文件夹名称或绝对路径": "请输入自定义日志文件夹名称或绝对路径",
|
||||
"请输入自定义日志文件夹名称或 /dev/null": "请输入自定义日志文件夹名称或 /dev/null",
|
||||
"日志名称只能包含字母、数字、下划线和连字符": "日志名称只能包含字母、数字、下划线和连字符",
|
||||
"日志名称不能超过100个字符": "日志名称不能超过100个字符"
|
||||
}
|
||||
|
||||
@@ -180,6 +180,42 @@ const CronModal = ({
|
||||
<Form.Item name="labels" label={intl.get('标签')}>
|
||||
<EditableTagGroup />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="log_name"
|
||||
label={intl.get('日志名称')}
|
||||
tooltip={intl.get(
|
||||
'自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内',
|
||||
)}
|
||||
rules={[
|
||||
{
|
||||
validator: (_, value) => {
|
||||
if (!value) return Promise.resolve();
|
||||
// Allow /dev/null specifically
|
||||
if (value === '/dev/null') return Promise.resolve();
|
||||
// Warn about other absolute paths (server will validate)
|
||||
if (value.startsWith('/')) {
|
||||
// We can't validate the exact path on frontend, but inform user
|
||||
return Promise.resolve();
|
||||
}
|
||||
// For relative names, enforce strict pattern
|
||||
if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
|
||||
return Promise.reject(
|
||||
intl.get('日志名称只能包含字母、数字、下划线和连字符'),
|
||||
);
|
||||
}
|
||||
if (value.length > 100) {
|
||||
return Promise.reject(intl.get('日志名称不能超过100个字符'));
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
placeholder={intl.get('请输入自定义日志文件夹名称或 /dev/null')}
|
||||
maxLength={200}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="task_before"
|
||||
label={intl.get('执行前')}
|
||||
@@ -312,4 +348,3 @@ const CronLabelModal = ({
|
||||
};
|
||||
|
||||
export { CronLabelModal, CronModal as default };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user