shell 增加国际化

This commit is contained in:
whyour 2026-06-14 16:45:53 +08:00
parent 0ee0b83207
commit b5a5fb3be6
16 changed files with 420 additions and 94 deletions

1
.gitignore vendored
View File

@ -31,3 +31,4 @@ __pycache__
/shell/preload/lang_env.sh
.deepseek/
.claude/

43
AGENTS.md Normal file
View File

@ -0,0 +1,43 @@
<!-- gitnexus:start -->
# GitNexus — Code Intelligence
This project is indexed by GitNexus as **qinglong** (2740 symbols, 6583 relationships, 230 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
> Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939).
## Always Do
- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
- **MUST run `detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows. For regression review, compare against the default branch: `detect_changes({scope: "compare", base_ref: "develop"})`.
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
- When exploring unfamiliar code, use `query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `context({name: "symbolName"})`.
## Never Do
- NEVER edit a function, class, or method without first running `impact` on it.
- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
- NEVER rename symbols with find-and-replace — use `rename` which understands the call graph.
- NEVER commit changes without running `detect_changes()` to check affected scope.
## Resources
| Resource | Use for |
|----------|---------|
| `gitnexus://repo/qinglong/context` | Codebase overview, check index freshness |
| `gitnexus://repo/qinglong/clusters` | All functional areas |
| `gitnexus://repo/qinglong/processes` | All execution flows |
| `gitnexus://repo/qinglong/process/{name}` | Step-by-step execution trace |
## CLI
| Task | Read this skill file |
|------|---------------------|
| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
<!-- gitnexus:end -->

43
CLAUDE.md Normal file
View File

@ -0,0 +1,43 @@
<!-- gitnexus:start -->
# GitNexus — Code Intelligence
This project is indexed by GitNexus as **qinglong** (2740 symbols, 6583 relationships, 230 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
> Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939).
## Always Do
- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
- **MUST run `detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows. For regression review, compare against the default branch: `detect_changes({scope: "compare", base_ref: "develop"})`.
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
- When exploring unfamiliar code, use `query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `context({name: "symbolName"})`.
## Never Do
- NEVER edit a function, class, or method without first running `impact` on it.
- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
- NEVER rename symbols with find-and-replace — use `rename` which understands the call graph.
- NEVER commit changes without running `detect_changes()` to check affected scope.
## Resources
| Resource | Use for |
|----------|---------|
| `gitnexus://repo/qinglong/context` | Codebase overview, check index freshness |
| `gitnexus://repo/qinglong/clusters` | All functional areas |
| `gitnexus://repo/qinglong/processes` | All execution flows |
| `gitnexus://repo/qinglong/process/{name}` | Step-by-step execution trace |
## CLI
| Task | Read this skill file |
|------|---------------------|
| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
<!-- gitnexus:end -->

View File

@ -50,9 +50,9 @@ add_cron_api() {
code=$(echo "$api" | jq -r .code)
message=$(echo "$api" | jq -r .message)
if [[ $code == 200 ]]; then
echo -e "$name -> 添加成功"
t '%s -> 添加成功' "$name"
else
echo -e "$name -> 添加失败(${message})"
t '%s -> 添加失败(%s)' "$name" "$message"
fi
}
@ -81,9 +81,9 @@ update_cron_api() {
code=$(echo "$api" | jq -r .code)
message=$(echo "$api" | jq -r .message)
if [[ $code == 200 ]]; then
echo -e "$name -> 更新成功"
t '%s -> 更新成功' "$name"
else
echo -e "$name -> 更新失败(${message})"
t '%s -> 更新失败(%s)' "$name" "$message"
fi
}
@ -108,9 +108,9 @@ update_cron_command_api() {
code=$(echo "$api" | jq -r .code)
message=$(echo "$api" | jq -r .message)
if [[ $code == 200 ]]; then
echo -e "$command -> 更新成功"
t '%s -> 更新成功' "$command"
else
echo -e "$command -> 更新失败(${message})"
t '%s -> 更新失败(%s)' "$command" "$message"
fi
}
@ -128,9 +128,9 @@ del_cron_api() {
code=$(echo "$api" | jq -r .code)
message=$(echo "$api" | jq -r .message)
if [[ $code == 200 ]]; then
echo -e "成功"
t '成功'
else
echo -e "失败(${message})"
t '失败(%s)' "$message"
fi
}
@ -175,9 +175,9 @@ notify_api() {
code=$(echo "$api" | jq -r .code)
message=$(echo "$api" | jq -r .message)
if [[ $code == 200 ]]; then
echo -e "通知发送成功🎉"
t '通知发送成功🎉'
else
echo -e "通知失败(${message})"
t '通知失败(%s)' "$message"
fi
}
@ -214,9 +214,9 @@ update_auth_config() {
code=$(echo "$api" | jq -r .code)
message=$(echo "$api" | jq -r .message)
if [[ $code == 200 ]]; then
echo -e "${tip}成功🎉"
t '%s成功🎉' "$tip"
else
echo -e "${tip}失败(${message})"
t '%s失败(%s)' "$tip" "$message"
fi
}

View File

@ -8,7 +8,7 @@ else
repo_path="${dir_repo}/diybot"
fi
echo -e "\n1、安装bot依赖...\n"
t '\n1、安装bot依赖...\n'
os_name="${QL_OS_TYPE:-}"
if [ -z "$os_name" ]; then
os_name=$(source /etc/os-release && echo "$ID")
@ -28,13 +28,13 @@ case "$os_name" in
$SUDO apt-get install -y gcc python3-dev musl-dev zlib1g-dev libjpeg-dev libfreetype-dev
;;
*)
echo -e "暂不支持此系统 $os_name"
t '暂不支持此系统 %s' "$os_name"
exit 1
;;
esac
echo -e "\nbot依赖安装成功...\n"
t '\nbot依赖安装成功...\n'
echo -e "2、下载bot所需文件...\n"
t '2、下载bot所需文件...\n'
if [[ ! -d ${repo_path}/.git ]]; then
rm -rf ${repo_path}
git_clone_scripts ${url} ${repo_path} "main"
@ -44,9 +44,9 @@ cp -rf "$repo_path/jbot" $dir_data
if [[ ! -f "$dir_config/bot.json" ]]; then
cp -f "$repo_path/config/bot.json" "$dir_config"
fi
echo -e "\nbot文件下载成功...\n"
t '\nbot文件下载成功...\n'
echo -e "3、安装python3依赖...\n"
t '3、安装python3依赖...\n'
cp -f "$repo_path/jbot/requirements.txt" "$dir_data"
cd $dir_data
@ -56,11 +56,11 @@ cat requirements.txt | while read LREAD; do
fi
done
echo -e "\npython3依赖安装成功...\n"
t '\npython3依赖安装成功...\n'
echo -e "4、启动bot程序...\n"
t '4、启动bot程序...\n'
make_dir $dir_log/bot
cd $dir_data
ps -eo pid,command | grep "python3 -m jbot" | grep -v grep | awk '{print $1}' | xargs kill -9 2>/dev/null
nohup python3 -m jbot >$dir_log/bot/nohup.log 2>&1 &
echo -e "bot启动成功...\n"
t 'bot启动成功...\n'

View File

@ -1,29 +1,29 @@
#!/usr/bin/env bash
reset_env() {
echo -e "---> 1. 开始检测配置文件\n"
t '---> 1. 开始检测配置文件\n'
fix_config
echo -e "---> 配置文件检测完成\n"
t '---> 配置文件检测完成\n'
echo -e "---> 2. 开始安装青龙依赖\n"
t '---> 2. 开始安装青龙依赖\n'
npm_install_2 $dir_root
echo -e "---> 青龙依赖安装完成\n"
t '---> 青龙依赖安装完成\n'
echo -e "---> 脚本依赖安装完成\n"
t '---> 脚本依赖安装完成\n'
}
copy_dep() {
echo -e "---> 1. 复制通知文件\n"
echo -e "---> 复制一份 $file_notify_py_sample$file_notify_py\n"
t '---> 1. 复制通知文件\n'
t '---> 复制一份 %s 为 %s\n' "$file_notify_py_sample" "$file_notify_py"
cp -fv $file_notify_py_sample $file_notify_py
echo
echo -e "---> 复制一份 $file_notify_js_sample$file_notify_js\n"
t '---> 复制一份 %s 为 %s\n' "$file_notify_js_sample" "$file_notify_js"
cp -fv $file_notify_js_sample $file_notify_js
echo -e "---> 通知文件复制完成\n"
t '---> 通知文件复制完成\n'
}
pm2_log() {
echo -e "---> pm2日志"
t '---> pm2日志'
local panelOut="/root/.pm2/logs/qinglong-out.log"
local panelError="/root/.pm2/logs/qinglong-error.log"
tail -n 300 "$panelOut"
@ -32,9 +32,10 @@ pm2_log() {
check_ql() {
local api=$(curl -s --noproxy "*" "http://localhost:${ql_port}")
echo -e "\n=====> 检测面板\n\n$api\n"
t '\n=====> 检测面板'
echo -e "\n\n$api\n"
if [[ $api =~ "<div id=\"root\"></div>" ]]; then
echo -e "=====> 面板服务启动正常\n"
t '=====> 面板服务启动正常\n'
fi
}
@ -49,14 +50,15 @@ check_pm2() {
-H 'Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7' \
--compressed
)
echo -e "\n=====> 检测后台\n\n$api\n"
t '\n=====> 检测后台'
echo -e "\n\n$api\n"
if [[ $api =~ "{\"code\"" ]]; then
echo -e "=====> 后台服务启动正常\n"
t '=====> 后台服务启动正常\n'
fi
}
main() {
echo -e "=====> 开始检测"
t '=====> 开始检测'
npm i -g pnpm@8.3.1 pm2 ts-node
reset_env
@ -64,7 +66,7 @@ main() {
check_ql
check_pm2
reload_pm2
echo -e "\n=====> 检测结束\n"
t '\n=====> 检测结束\n'
}
main

105
shell/lang/en.sh Normal file
View File

@ -0,0 +1,105 @@
# English language pack
declare -gA LANG_MESSAGES=(
['任务随机延迟 %s 秒,将于 %s 开始,配置文件参数 RandomDelay 置空可取消延迟\n']='Task delayed %s seconds, will start at %s. Set RandomDelay to empty to cancel delay\n'
['开始执行...\n']='Starting execution...\n'
['已停止']='Stopped'
['完成']='Completed'
['失败(退出码 %s)']='Failed (exit code %s)'
['安装 %s 依赖包...\n']='Installing %s dependencies...\n'
['开始拉取仓库 %s 到 %s\n']='Cloning repository %s to %s\n'
['添加成功']='Added successfully'
['添加失败(%s)']='Add failed (%s)'
['更新成功']='Updated successfully'
['更新失败(%s)']='Update failed (%s)'
['成功']='Success'
['失败(%s)']='Failed (%s)'
['通知发送成功🎉']='Notification sent successfully 🎉'
['通知失败(%s)']='Notification failed (%s)'
['当前有以下脚本可以运行:']='Available scripts:'
['暂无脚本可以执行']='No scripts available'
['警告:工作目录不存在 %s']='Warning: working directory does not exist: %s'
['\n缺少并发运行的环境变量参数']='\nMissing concurrency environment variable'
['\n缺少单独运行的参数 task xxx.js desi Test']='\nMissing parameter: task xxx.js desi Test'
['暂不支持此系统 %s']='Unsupported system: %s'
['检测到 pm2 服务正在运行']='pm2 service is running'
['npm 模块位置: %s']='npm module location: %s'
['导入数据成功 %s']='Data imported successfully: %s'
['导出数据成功 %s']='Data exported successfully: %s'
['当前版本: %s / 最新版本: %s']='Current: %s / Latest: %s'
['已是最新版本']='Already up to date'
['%s 个定时任务正在运行']='%s scheduled tasks running'
['执行前置命令\n']='Running pre-command\n'
['\n执行前置命令结束\n']='\nPre-command finished\n'
['\n执行后置命令\n']='\nRunning post-command\n'
['\n执行后置命令结束']='\nPost-command finished'
['警告: PM2 启动失败 (退出码: %s),可能是由于硬件不兼容']='Warning: PM2 start failed (exit code: %s), possibly due to hardware incompatibility'
['正在尝试直接使用 Node.js 启动服务...']='Attempting to start service with Node.js directly...'
['已使用 Node.js 直接启动服务 (PID: %s)']='Service started with Node.js directly (PID: %s)'
['注意: 使用此模式时,部分 PM2 管理功能将不可用']='Note: some PM2 management features are unavailable in this mode'
['## 开始执行... %s\n']='## Starting... %s\n'
['\n## 已停止 🛑... %s 耗时 %s 秒%s']='\n## Stopped 🛑... %s took %s seconds%s'
['\n## 完成 ✅... %s 耗时 %s 秒%s']='\n## Completed ✅... %s took %s seconds%s'
['\n## 失败 ❌(退出码 %s)... %s 耗时 %s 秒%s']='\n## Failed ❌(exit code %s)... %s took %s seconds%s'
['%s -> 添加成功']='%s -> Added successfully'
['%s -> 添加失败(%s)']='%s -> Add failed (%s)'
['%s -> 更新成功']='%s -> Updated successfully'
['%s -> 更新失败(%s)']='%s -> Update failed (%s)'
['%s成功🎉']='%s succeeded 🎉'
['%s失败(%s)']='%s failed (%s)'
['检测到有%s的定时任务:']='Found %s scheduled tasks:'
['\n开始尝试自动删除失效的定时任务...']='\nAttempting to remove invalid scheduled tasks...'
['\n开始尝试自动添加定时任务...']='\nAttempting to add scheduled tasks...'
['拉取 %s 成功...\n']='Pull %s succeeded...\n'
['拉取 %s 失败,请检查日志...\n']='Pull %s failed, check logs...\n'
['开始下载:%s 保存路径:%s\n']='Downloading: %s to: %s\n'
['下载 %s 成功...\n']='Download %s succeeded...\n'
['下载 %s 失败,保留之前正常下载的版本...\n']='Download %s failed, keeping previous version...\n'
['%s文件不存在跳过执行...\n']='%s does not exist, skipping...\n'
['使用 %s 源更新...\n']='Updating using %s mirror...\n'
['更新青龙源文件成功...\n']='Qinglong source updated successfully\n'
['更新青龙源文件失败,请检查网络...\n']='Qinglong source update failed, check network\n'
['更新青龙静态资源成功...\n']='Static assets updated successfully\n'
['更新青龙静态资源失败,请检查网络...\n']='Static assets update failed, check network\n'
['\n开始检测依赖...\n']='\nChecking dependencies...\n'
['\n依赖检测安装成功...\n']='\nDependencies installed successfully\n'
['更新包下载成功...\n']='Package download succeeded\n'
['\n依赖检测安装失败请检查网络...\n']='\nDependency installation failed, check network\n'
['\n1、安装bot依赖...\n']='\n1. Installing bot dependencies...\n'
['\nbot依赖安装成功...\n']='\nBot dependencies installed\n'
['2、下载bot所需文件...\n']='2. Downloading bot files...\n'
['\nbot文件下载成功...\n']='\nBot files downloaded\n'
['3、安装python3依赖...\n']='3. Installing python3 dependencies...\n'
['\npython3依赖安装成功...\n']='\nPython3 dependencies installed\n'
['4、启动bot程序...\n']='4. Starting bot...\n'
['bot启动成功...\n']='Bot started successfully\n'
# check.sh
['---> 1. 开始检测配置文件\n']='---> 1. Checking config...\n'
['---> 配置文件检测完成\n']='---> Config check complete\n'
['---> 2. 开始安装青龙依赖\n']='---> 2. Installing qinglong dependencies...\n'
['---> 青龙依赖安装完成\n']='---> Dependencies installed\n'
['---> 脚本依赖安装完成\n']='---> Script dependencies installed\n'
['---> 1. 复制通知文件\n']='---> 1. Copying notification files...\n'
['---> 复制一份 %s 为 %s\n']='---> Copying %s to %s\n'
['---> 通知文件复制完成\n']='---> Notification files copied\n'
['---> pm2日志']='---> pm2 log'
['\n=====> 检测面板']='\n=====> Checking panel'
['=====> 面板服务启动正常\n']='=====> Panel service running normally\n'
['\n=====> 检测后台']='\n=====> Checking backend'
['=====> 后台服务启动正常\n']='=====> Backend service running normally\n'
['=====> 开始检测']='=====> Starting check'
['\n=====> 检测结束\n']='\n=====> Check complete\n'
# rmlog.sh
['查询文件 %s']='Checking file: %s'
['删除中~']='Deleting...'
['正在被 %s 使用,跳过~']='In use by %s, skipping...'
['查找旧日志文件中...\n']='Looking for old log files...\n'
['删除旧日志执行完毕\n']='Old log cleanup complete\n'
# start.sh
['未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装']='Module not found. Run: npm i -g @whyour/qinglong'
['请先手动设置 export QL_DIR=%s环境变量并手动添加到系统环境变量然后再次执行命令 qinglong 启动服务']='Set env: export QL_DIR=%s, then run qinglong to start'
['请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量']='Set QL_DATA_DIR (absolute path ending with /data, e.g. /ql/data)'
['QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data如果有历史数据请新建 data 目录,把历史数据放到 data 目录中']='QL_DATA_DIR must end with /data, e.g. /ql/data'
['暂不支持此系统部署 %s']='Unsupported system for deployment: %s'
# update.sh
['命令输入错误...\n']='Invalid command...\n'
)

105
shell/lang/zh.sh Normal file
View File

@ -0,0 +1,105 @@
# 中文语言包zh key → zh value 恒等en 包做实际翻译)
declare -gA LANG_MESSAGES=(
['任务随机延迟 %s 秒,将于 %s 开始,配置文件参数 RandomDelay 置空可取消延迟\n']='任务随机延迟 %s 秒,将于 %s 开始,配置文件参数 RandomDelay 置空可取消延迟\n'
['开始执行...\n']='开始执行...\n'
['已停止']='已停止'
['完成']='完成'
['失败(退出码 %s)']='失败(退出码 %s)'
['安装 %s 依赖包...\n']='安装 %s 依赖包...\n'
['开始拉取仓库 %s 到 %s\n']='开始拉取仓库 %s 到 %s\n'
['添加成功']='添加成功'
['添加失败(%s)']='添加失败(%s)'
['更新成功']='更新成功'
['更新失败(%s)']='更新失败(%s)'
['成功']='成功'
['失败(%s)']='失败(%s)'
['通知发送成功🎉']='通知发送成功🎉'
['通知失败(%s)']='通知失败(%s)'
['当前有以下脚本可以运行:']='当前有以下脚本可以运行:'
['暂无脚本可以执行']='暂无脚本可以执行'
['警告:工作目录不存在 %s']='警告:工作目录不存在 %s'
['\n缺少并发运行的环境变量参数']='\n缺少并发运行的环境变量参数'
['\n缺少单独运行的参数 task xxx.js desi Test']='\n缺少单独运行的参数 task xxx.js desi Test'
['暂不支持此系统 %s']='暂不支持此系统 %s'
['检测到 pm2 服务正在运行']='检测到 pm2 服务正在运行'
['npm 模块位置: %s']='npm 模块位置: %s'
['导入数据成功 %s']='导入数据成功 %s'
['导出数据成功 %s']='导出数据成功 %s'
['当前版本: %s / 最新版本: %s']='当前版本: %s / 最新版本: %s'
['已是最新版本']='已是最新版本'
['%s 个定时任务正在运行']='%s 个定时任务正在运行'
['执行前置命令\n']='执行前置命令\n'
['\n执行前置命令结束\n']='\n执行前置命令结束\n'
['\n执行后置命令\n']='\n执行后置命令\n'
['\n执行后置命令结束']='\n执行后置命令结束'
['警告: PM2 启动失败 (退出码: %s),可能是由于硬件不兼容']='警告: PM2 启动失败 (退出码: %s),可能是由于硬件不兼容'
['正在尝试直接使用 Node.js 启动服务...']='正在尝试直接使用 Node.js 启动服务...'
['已使用 Node.js 直接启动服务 (PID: %s)']='已使用 Node.js 直接启动服务 (PID: %s)'
['注意: 使用此模式时,部分 PM2 管理功能将不可用']='注意: 使用此模式时,部分 PM2 管理功能将不可用'
['## 开始执行... %s\n']='## 开始执行... %s\n'
['\n## 已停止 🛑... %s 耗时 %s 秒%s']='\n## 已停止 🛑... %s 耗时 %s 秒%s'
['\n## 完成 ✅... %s 耗时 %s 秒%s']='\n## 完成 ✅... %s 耗时 %s 秒%s'
['\n## 失败 ❌(退出码 %s)... %s 耗时 %s 秒%s']='\n## 失败 ❌(退出码 %s)... %s 耗时 %s 秒%s'
['%s -> 添加成功']='%s -> 添加成功'
['%s -> 添加失败(%s)']='%s -> 添加失败(%s)'
['%s -> 更新成功']='%s -> 更新成功'
['%s -> 更新失败(%s)']='%s -> 更新失败(%s)'
['%s成功🎉']='%s成功🎉'
['%s失败(%s)']='%s失败(%s)'
['检测到有%s的定时任务:']='检测到有%s的定时任务:'
['\n开始尝试自动删除失效的定时任务...']='\n开始尝试自动删除失效的定时任务...'
['\n开始尝试自动添加定时任务...']='\n开始尝试自动添加定时任务...'
['拉取 %s 成功...\n']='拉取 %s 成功...\n'
['拉取 %s 失败,请检查日志...\n']='拉取 %s 失败,请检查日志...\n'
['开始下载:%s 保存路径:%s\n']='开始下载:%s 保存路径:%s\n'
['下载 %s 成功...\n']='下载 %s 成功...\n'
['下载 %s 失败,保留之前正常下载的版本...\n']='下载 %s 失败,保留之前正常下载的版本...\n'
['%s文件不存在跳过执行...\n']='%s文件不存在跳过执行...\n'
['使用 %s 源更新...\n']='使用 %s 源更新...\n'
['更新青龙源文件成功...\n']='更新青龙源文件成功...\n'
['更新青龙源文件失败,请检查网络...\n']='更新青龙源文件失败,请检查网络...\n'
['更新青龙静态资源成功...\n']='更新青龙静态资源成功...\n'
['更新青龙静态资源失败,请检查网络...\n']='更新青龙静态资源失败,请检查网络...\n'
['\n开始检测依赖...\n']='\n开始检测依赖...\n'
['\n依赖检测安装成功...\n']='\n依赖检测安装成功...\n'
['更新包下载成功...\n']='更新包下载成功...\n'
['\n依赖检测安装失败请检查网络...\n']='\n依赖检测安装失败请检查网络...\n'
['\n1、安装bot依赖...\n']='\n1、安装bot依赖...\n'
['\nbot依赖安装成功...\n']='\nbot依赖安装成功...\n'
['2、下载bot所需文件...\n']='2、下载bot所需文件...\n'
['\nbot文件下载成功...\n']='\nbot文件下载成功...\n'
['3、安装python3依赖...\n']='3、安装python3依赖...\n'
['\npython3依赖安装成功...\n']='\npython3依赖安装成功...\n'
['4、启动bot程序...\n']='4、启动bot程序...\n'
['bot启动成功...\n']='bot启动成功...\n'
# check.sh
['---> 1. 开始检测配置文件\n']='---> 1. 开始检测配置文件\n'
['---> 配置文件检测完成\n']='---> 配置文件检测完成\n'
['---> 2. 开始安装青龙依赖\n']='---> 2. 开始安装青龙依赖\n'
['---> 青龙依赖安装完成\n']='---> 青龙依赖安装完成\n'
['---> 脚本依赖安装完成\n']='---> 脚本依赖安装完成\n'
['---> 1. 复制通知文件\n']='---> 1. 复制通知文件\n'
['---> 复制一份 %s 为 %s\n']='---> 复制一份 %s 为 %s\n'
['---> 通知文件复制完成\n']='---> 通知文件复制完成\n'
['---> pm2日志']='---> pm2日志'
['\n=====> 检测面板']='\n=====> 检测面板'
['=====> 面板服务启动正常\n']='=====> 面板服务启动正常\n'
['\n=====> 检测后台']='\n=====> 检测后台'
['=====> 后台服务启动正常\n']='=====> 后台服务启动正常\n'
['=====> 开始检测']='=====> 开始检测'
['\n=====> 检测结束\n']='\n=====> 检测结束\n'
# rmlog.sh
['查询文件 %s']='查询文件 %s'
['删除中~']='删除中~'
['正在被 %s 使用,跳过~']='正在被 %s 使用,跳过~'
['查找旧日志文件中...\n']='查找旧日志文件中...\n'
['删除旧日志执行完毕\n']='删除旧日志执行完毕\n'
# start.sh
['未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装']='未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装'
['请先手动设置 export QL_DIR=%s环境变量并手动添加到系统环境变量然后再次执行命令 qinglong 启动服务']='请先手动设置 export QL_DIR=%s环境变量并手动添加到系统环境变量然后再次执行命令 qinglong 启动服务'
['请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量']='请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量'
['QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data如果有历史数据请新建 data 目录,把历史数据放到 data 目录中']='QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data如果有历史数据请新建 data 目录,把历史数据放到 data 目录中'
['暂不支持此系统部署 %s']='暂不支持此系统部署 %s'
# update.sh
['命令输入错误...\n']='命令输入错误...\n'
)

View File

@ -30,7 +30,7 @@ random_delay() {
else
start_time=$(date -d "+${delay_second} seconds" "+%Y-%m-%d %H:%M:%S")
fi
echo -e "任务随机延迟 $delay_second 秒,将于 $start_time 开始,配置文件参数 RandomDelay 置空可取消延迟 \n"
t '任务随机延迟 %s 秒,将于 %s 开始,配置文件参数 RandomDelay 置空可取消延迟\n' "$delay_second" "$start_time"
sleep $delay_second
fi
}
@ -122,7 +122,7 @@ enter_script_workdir() {
fi
return
fi
echo -e "警告:工作目录不存在 ${_target_dir}"
t '警告:工作目录不存在 %s' "${_target_dir}"
fi
cd $dir_scripts
@ -173,7 +173,7 @@ run_concurrent() {
local env_param="$2"
local num_param=$(echo "$3" | perl -pe "s|.*$2(.*)|\1|" | awk '{$1=$1};1')
if [[ ! $env_param ]]; then
echo -e "\n 缺少并发运行的环境变量参数"
t '\n缺少并发运行的环境变量参数'
exit 1
fi
@ -210,7 +210,7 @@ run_designated() {
local env_param="$2"
local num_param=$(echo "$3" | perl -pe "s|.*$2(.*)|\1|" | awk '{$1=$1};1')
if [[ ! $env_param ]]; then
echo -e "\n 缺少单独运行的参数 task xxx.js desi Test"
t '\n缺少单独运行的参数 task xxx.js desi Test'
exit 1
fi

View File

@ -22,12 +22,12 @@ remove_js_log() {
if [[ $diff_time -gt $((${days} * 86400)) ]]; then
local log_path=$(echo "$log" | sed "s,${dir_log}/,,g")
local result=$(find_cron_api "log_path=$log_path")
echo -e "查询文件 $log_path"
t '查询文件 %s' "$log_path"
if [[ -z $result ]]; then
echo -e "删除中~"
t '删除中~'
rm -vf $log
else
echo -e "正在被 $result 使用,跳过~"
t '正在被 %s 使用,跳过~' "$result"
fi
fi
done
@ -43,8 +43,8 @@ remove_empty_dir() {
}
if [[ ${days} ]]; then
echo -e "查找旧日志文件中...\n"
t '查找旧日志文件中...\n'
remove_js_log
remove_empty_dir
echo -e "删除旧日志执行完毕\n"
t '删除旧日志执行完毕\n'
fi

View File

@ -80,6 +80,15 @@ import_config() {
[[ -f $file_config_user ]] && . $file_config_user
[[ -f $dir_preload/lang_env.sh ]] && . $dir_preload/lang_env.sh
# 加载语言包bash 4+ 支持 declare -A不兼容时回退输出中文 key
local lang=${QL_LANG:-zh}
local lang_file="$dir_shell/lang/${lang}.sh"
if [[ ${BASH_VERSINFO[0]} -ge 4 ]] && [[ -f $lang_file ]]; then
. $lang_file
elif [[ ${BASH_VERSINFO[0]} -ge 4 ]]; then
. "$dir_shell/lang/zh.sh"
fi
load_ql_envs
command_timeout_time=${CommandTimeoutTime:-""}
file_extensions=${RepoFileExtensions:-"js py"}
@ -92,6 +101,18 @@ import_config() {
fi
}
t() {
local key="$1"
shift
local msg
if declare -p LANG_MESSAGES &>/dev/null; then
msg="${LANG_MESSAGES["$key"]}"
fi
[[ -z $msg ]] && msg="$key"
# shellcheck disable=SC2059
printf "$msg\n" "$@"
}
set_proxy() {
local proxy="$1"
if [[ $proxy ]]; then
@ -226,7 +247,7 @@ npm_install_2() {
local dir_work=$1
cd $dir_work
echo -e "安装 $dir_work 依赖包...\n"
t '安装 %s 依赖包...\n' "$dir_work"
npm_install_sub
cd $dir_current
}
@ -245,7 +266,7 @@ git_clone_scripts() {
local branch="$3"
local proxy="$4"
[[ $branch ]] && local part_cmd="-b $branch "
echo -e "开始拉取仓库 ${uniq_path}$dir\n"
t '开始拉取仓库 %s 到 %s\n' "${uniq_path}" "$dir"
set_proxy "$proxy"
@ -278,8 +299,8 @@ reload_pm2() {
return 0
else
local exit_code=$?
echo "警告: PM2 启动失败 (退出码: $exit_code),可能是由于硬件不兼容"
echo "正在尝试直接使用 Node.js 启动服务..."
t '警告: PM2 启动失败 (退出码: %s),可能是由于硬件不兼容' "$exit_code"
t '正在尝试直接使用 Node.js 启动服务...'
# Kill any existing node processes for qinglong
pkill -f "node.*static/build/app.js" 2>/dev/null || true
@ -288,8 +309,8 @@ reload_pm2() {
nohup node static/build/app.js > $dir_log/qinglong.log 2>&1 &
local node_pid=$!
echo "已使用 Node.js 直接启动服务 (PID: $node_pid)"
echo "注意: 使用此模式时,部分 PM2 管理功能将不可用"
t '已使用 Node.js 直接启动服务 (PID: %s)' "$node_pid"
t '注意: 使用此模式时,部分 PM2 管理功能将不可用'
return 0
fi
}
@ -361,16 +382,16 @@ handle_task_start() {
error_message=", 任务状态更新失败(${error})"
fi
fi
echo -e "## 开始执行... ${begin_time}${error_message}\n"
t '## 开始执行... %s\n' "${begin_time}${error_message}"
}
run_task_before() {
. $file_task_before "$@"
if [[ ${task_before:=} ]]; then
echo -e "执行前置命令\n"
t '执行前置命令\n'
eval "${task_before%;}"
echo -e "\n执行前置命令结束\n"
t '\n执行前置命令结束\n'
fi
}
@ -378,9 +399,9 @@ run_task_after() {
. $file_task_after "$@"
if [[ ${task_after:=} ]]; then
echo -e "\n执行后置命令\n"
t '\n执行后置命令\n'
eval "${task_after%;}"
echo -e "\n执行后置命令结束"
t '\n执行后置命令结束'
fi
}
@ -402,11 +423,11 @@ handle_task_end() {
record_cron_stat "$ID" "${exit_code:-0}" "$diff_time"
if [[ "${MANUAL:=}" == "true" ]]; then
echo -e "\n## 已停止 🛑... $end_time 耗时 $diff_time${error_message:=}     "
t '\n## 已停止 🛑... %s 耗时 %s 秒%s' "$end_time" "$diff_time" "${error_message:=}     "
elif [[ $exit_code -eq 0 ]]; then
echo -e "\n## 完成 ✅... $end_time 耗时 $diff_time${error_message:=}     "
t '\n## 完成 ✅... %s 耗时 %s 秒%s' "$end_time" "$diff_time" "${error_message:=}     "
else
echo -e "\n## 失败 ❌(退出码 ${exit_code})... $end_time 耗时 $diff_time${error_message:=}     "
t '\n## 失败 ❌(退出码 %s)... %s 耗时 %s 秒%s' "$exit_code" "$end_time" "$diff_time" "${error_message:=}     "
fi
}

View File

@ -12,23 +12,23 @@ if [[ ! $QL_DIR ]]; then
elif [[ -d "$pnpm_dir/@whyour/qinglong" ]]; then
QL_DIR="$pnpm_dir/@whyour/qinglong"
else
echo -e "未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装"
t '未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装'
fi
if [[ $QL_DIR ]]; then
echo -e "请先手动设置 export QL_DIR=$QL_DIR,环境变量,并手动添加到系统环境变量,然后再次执行命令 qinglong 启动服务"
t '请先手动设置 export QL_DIR=%s,环境变量,并手动添加到系统环境变量,然后再次执行命令 qinglong 启动服务' "$QL_DIR"
fi
exit 1
fi
if [[ ! $QL_DATA_DIR ]]; then
echo -e "请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量"
t '请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量'
exit 1
fi
if [[ $QL_DATA_DIR != */data ]]; then
echo -e "QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data如果有历史数据请新建 data 目录,把历史数据放到 data 目录中"
t 'QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data如果有历史数据请新建 data 目录,把历史数据放到 data 目录中'
exit 1
fi
@ -69,7 +69,7 @@ if [[ $command != "reload" ]]; then
$SUDO apt-get install -y git curl wget tzdata perl openssl jq nginx procps netcat-openbsd openssh-client
;;
*)
echo -e "暂不支持此系统部署 $os_name"
t '暂不支持此系统部署 %s' "$os_name"
exit 1
;;
esac

View File

@ -4,7 +4,13 @@ dir_shell=$QL_DIR/shell
. $dir_shell/share.sh
. $dir_shell/api.sh
trap "single_hanle" 2 3 20 15 14 19 1
trap 'single_hanle SIGINT' INT
trap 'single_hanle SIGTERM' TERM
trap 'single_hanle SIGHUP' HUP
trap 'single_hanle SIGALRM' ALRM
trap 'single_hanle SIGTSTP' TSTP
trap 'single_hanle SIGQUIT' QUIT
single_hanle() {
_task_exit_code="${_task_exit_code:-$?}"
[[ "$_task_exit_code" == "0" ]] && _task_exit_code="1"

View File

@ -33,7 +33,7 @@ output_list_add_drop() {
local list=$1
local type=$2
if [[ -s $list ]]; then
echo -e "检测到有${type}的定时任务:"
t '检测到有%s的定时任务:' "$type"
cat $list
fi
}
@ -45,7 +45,7 @@ del_cron() {
local path=$2
local detail=""
local ids=""
echo -e "\n开始尝试自动删除失效的定时任务..."
t '\n开始尝试自动删除失效的定时任务...'
for cron in $(cat $list_drop); do
local id=$(cat $list_crontab_user | grep -E "$cmd_task.* $cron" | perl -pe "s|.*ID=(.*) $cmd_task.* $cron\.*|\1|" | head -1 | awk -F " " '{print $1}')
if [[ $ids ]]; then
@ -76,7 +76,7 @@ del_cron() {
add_cron() {
local list_add=$1
local path=$2
echo -e "\n开始尝试自动添加定时任务..."
t '\n开始尝试自动添加定时任务...'
local detail=""
cd $dir_scripts
for file in $(cat $list_add); do
@ -136,10 +136,10 @@ update_repo() {
git_clone_scripts "${formatUrl}" ${repo_path} "${branch}" "${proxy}"
if [[ $exit_status -eq 0 ]]; then
echo -e "拉取 ${uniq_path} 成功...\n"
t '拉取 %s 成功...\n' "${uniq_path}"
diff_scripts "$repo_path" "$author" "$path" "$blackword" "$dependence" "$extensions" "$autoAddCron" "$autoDelCron"
else
echo -e "拉取 ${uniq_path} 失败,请检查日志...\n"
t '拉取 %s 失败,请检查日志...\n' "${uniq_path}"
fi
}
@ -160,7 +160,7 @@ update_raw() {
local raw_url="$url"
local suffix="${raw_url##*.}"
local raw_file_name="${uniq_path}.${suffix}"
echo -e "开始下载:${raw_url} \n\n保存路径$dir_raw/${raw_file_name}\n"
t '开始下载:%s 保存路径:%s\n' "${raw_url}" "$dir_raw/${raw_file_name}"
set_proxy "$proxy"
wget -q --no-check-certificate -O "$dir_raw/${raw_file_name}.new" ${raw_url}
@ -169,7 +169,7 @@ update_raw() {
if [[ $? -eq 0 ]]; then
mv "$dir_raw/${raw_file_name}.new" "$dir_raw/${raw_file_name}"
echo -e "下载 ${raw_file_name} 成功...\n"
t '下载 %s 成功...\n' "${raw_file_name}"
cd $dir_raw
local filename="raw_${raw_file_name}"
local cron_id=$(cat $list_crontab_user | grep -E "$cmd_task.* $filename" | perl -pe "s|.*ID=(.*) $cmd_task.* $filename\.*|\1|" | head -1 | awk -F " " '{print $1}')
@ -196,7 +196,7 @@ update_raw() {
# update_cron_api "$cron_line:$cmd_task $filename:$cron_name:$cron_id"
fi
else
echo -e "下载 ${raw_file_name} 失败,保留之前正常下载的版本...\n"
t '下载 %s 失败,保留之前正常下载的版本...\n' "${raw_file_name}"
[[ -f "$dir_raw/${raw_file_name}.new" ]] && rm -f "$dir_raw/${raw_file_name}.new"
fi
@ -207,13 +207,13 @@ run_extra_shell() {
if [[ -f $file_extra_shell ]]; then
. $file_extra_shell
else
echo -e "$file_extra_shell文件不存在,跳过执行...\n"
t '%s文件不存在跳过执行...\n' "$file_extra_shell"
fi
}
## 脚本用法
usage() {
echo -e "$cmd_update 命令使用方法:"
t "$cmd_update 命令使用方法:"
echo -e "1. $cmd_update update # 更新并重启青龙"
echo -e "2. $cmd_update extra # 运行自定义脚本"
echo -e "3. $cmd_update raw <fileurl> # 更新单个脚本文件"
@ -268,7 +268,7 @@ update_qinglong() {
downloadQLUrl="https://github.com/whyour/qinglong/archive/refs/heads"
downloadStaticUrl="https://github.com/whyour/qinglong-static/archive/refs/heads"
fi
echo -e "使用 ${mirror} 源更新...\n"
t '使用 %s 源更新...\n' "${mirror}"
local primary_branch="master"
if [[ "${QL_BRANCH}" == "develop" ]] || [[ "${QL_BRANCH}" == "debian" ]] || [[ "${QL_BRANCH}" == "debian-dev" ]]; then
@ -279,13 +279,13 @@ update_qinglong() {
exit_status=$?
if [[ $exit_status -eq 0 ]]; then
echo -e "更新青龙源文件成功...\n"
t '更新青龙源文件成功...\n'
unzip -oq ${dir_tmp}/ql.zip -d ${dir_tmp}
update_qinglong_static
else
echo -e "更新青龙源文件失败,请检查网络...\n"
t '更新青龙源文件失败,请检查网络...\n'
fi
}
@ -294,30 +294,30 @@ update_qinglong_static() {
exit_status=$?
if [[ $exit_status -eq 0 ]]; then
echo -e "更新青龙静态资源成功...\n"
t '更新青龙静态资源成功...\n'
unzip -oq ${dir_tmp}/static.zip -d ${dir_tmp}
check_update_dep
else
echo -e "更新青龙静态资源失败,请检查网络...\n"
t '更新青龙静态资源失败,请检查网络...\n'
fi
}
check_update_dep() {
echo -e "\n开始检测依赖...\n"
t '\n开始检测依赖...\n'
if [[ $(diff $dir_root/package.json ${dir_tmp}/qinglong-${primary_branch}/package.json) ]]; then
npm_install_2 "${dir_tmp}/qinglong-${primary_branch}"
fi
if [[ $exit_status -eq 0 ]]; then
echo -e "\n依赖检测安装成功...\n"
echo -e "更新包下载成功..."
t '\n依赖检测安装成功...\n'
t '更新包下载成功...\n'
if [[ "$needRestart" == 'true' ]]; then
reload_qinglong "system"
fi
else
echo -e "\n依赖检测安装失败请检查网络...\n"
t '\n依赖检测安装失败请检查网络...\n'
fi
}
@ -514,7 +514,7 @@ main() {
if [[ -n $p2 ]]; then
update_repo "$p2" "$p3" "$p4" "$p5" "$p6" "$p7" "$p8" "$p9" "$p10"
else
eval echo -e "命令输入错误...\\\n" $cmd
t '命令输入错误...\n'
eval usage $cmd
fi
;;
@ -523,7 +523,7 @@ main() {
if [[ -n $p2 ]]; then
update_raw "$p2" "$p3" "$p4" "$p5"
else
eval echo -e "命令输入错误...\\\n" $cmd
t '命令输入错误...\n'
eval usage $cmd
fi
;;
@ -549,7 +549,7 @@ main() {
eval update_auth_config "\\\"username\\\":\\\"$p2\\\"" "重置用户名" $cmd
;;
*)
eval echo -e "命令输入错误...\\\n" $cmd
t '命令输入错误...\n'
eval usage $cmd
;;
esac

View File

@ -89,7 +89,7 @@ export default function () {
if (code === 200 && data.username) {
setUser(data);
if (location.pathname === '/') {
history.push('/crontab');
history.push('/dashboard');
}
}
needLoading && setLoading(false);
@ -218,7 +218,7 @@ export default function () {
if (['/login', '/initialization', '/error'].includes(location.pathname)) {
if (systemInfo?.isInitialized && location.pathname === '/initialization') {
history.push('/crontab');
history.push('/dashboard');
}
if (systemInfo || location.pathname === '/error') {

View File

@ -54,7 +54,7 @@ const Error = () => {
useEffect(() => {
if (user && user.username) {
history.push('/crontab');
history.push('/dashboard');
}
}, [user]);