diff --git a/en/kejilion.sh b/en/kejilion.sh index 93e3e7fe5..f4495aba9 100644 --- a/en/kejilion.sh +++ b/en/kejilion.sh @@ -1,5 +1,5 @@ #!/bin/bash -sh_v="4.4.9" +sh_v="4.4.10" gl_hui='\e[37m' @@ -2324,7 +2324,7 @@ check_nginx_compression() { # Check whether zstd is on and uncommented (the whole line starts with zstd on;) if grep -qE '^\s*zstd\s+on;' "$CONFIG_FILE"; then - zstd_status="zstd compression is enabled" + zstd_status="zstd compression is on" else zstd_status="" fi @@ -2673,7 +2673,7 @@ clear_container_rules() { iptables -D DOCKER-USER -p tcp -d "$container_ip" -j DROP fi - # Clear the rules that allow specified IPs + # Clear the rules that allow the specified IP if iptables -C DOCKER-USER -p tcp -s "$allowed_ip" -d "$container_ip" -j ACCEPT &>/dev/null; then iptables -D DOCKER-USER -p tcp -s "$allowed_ip" -d "$container_ip" -j ACCEPT fi @@ -2692,7 +2692,7 @@ clear_container_rules() { iptables -D DOCKER-USER -p udp -d "$container_ip" -j DROP fi - # Clear the rules that allow specified IPs + # Clear the rules that allow the specified IP if iptables -C DOCKER-USER -p udp -s "$allowed_ip" -d "$container_ip" -j ACCEPT &>/dev/null; then iptables -D DOCKER-USER -p udp -s "$allowed_ip" -d "$container_ip" -j ACCEPT fi @@ -3221,7 +3221,7 @@ f2b_sshd() { # Basic parameter configuration: ban duration (bantime), time window (findtime), number of retries (maxretry) # illustrate: -# - Prioritize writing to /etc/fail2ban/jail.d/sshd.local (overrides the default jail configuration and is not easy to lose when upgrading) +# - Prioritize writing to /etc/fail2ban/jail.d/sshd.local (overwrites the default jail configuration and is not easy to lose when upgrading) # - If it is Alpine and the jail names are different, still write sshd.local; Fail2Ban will match according to the jail name. f2b_basic_config() { root_use @@ -3602,7 +3602,7 @@ ldnmp_Proxy_backend() { list_stream_services() { STREAM_DIR="/home/web/stream.d" - printf "%-25s %-18s %-25s %-20s\n" "Service name" "Communication type" "local address" "Backend address" + printf "%-25s %-18s %-25s %-20s\n" "Service name" "Communication type" "Local address" "Backend address" if [ -z "$(ls -A "$STREAM_DIR")" ]; then return @@ -5094,7 +5094,7 @@ fetch_github_ssh_keys() { local base_dir="${2:-$HOME}" echo "Before proceeding, make sure you have added your SSH public key to your GitHub account:" - echo "1. Login${gh_https_url}github.com/settings/keys" + echo "1. Log in${gh_https_url}github.com/settings/keys" echo "2. Click New SSH key or Add SSH key" echo "3. Title can be filled in as desired (for example: Home Laptop 2026)" echo "4. Paste the contents of the local public key (usually the entire contents of ~/.ssh/id_ed25519.pub or id_rsa.pub) into the Key field" @@ -7213,7 +7213,7 @@ disk_manager() { send_stats "Hard disk management function" while true; do clear - echo "Hard drive partition management" + echo "Hard disk partition management" echo -e "${gl_huang}This feature is under internal testing and should not be used in a production environment.${gl_bai}" echo "------------------------" list_partitions @@ -7299,11 +7299,11 @@ add_task() { # Delete task delete_task() { send_stats "Delete sync task" - read -e -p "Please enter the task number to be deleted:" num + read -e -p "请输入要删除的任务编号: " num local task=$(sed -n "${num}p" "$CONFIG_FILE") if [[ -z "$task" ]]; then - echo "Error: The corresponding task was not found." + echo "错误:未找到对应的任务。" return fi @@ -8083,7 +8083,7 @@ docker_ssh_migration() { local VOL_ARGS="" for path in $VOL_PATHS; do VOL_ARGS+="-v $path:$path "; done - # mirror + # Mirror local IMAGE IMAGE=$(jq -r '.[0].Config.Image' "$inspect_file") @@ -10783,7 +10783,7 @@ EOF } - + openclaw_api_manage_list() { local config_file="${HOME}/.openclaw/openclaw.json" send_stats "OpenClaw API List" @@ -11500,7 +11500,7 @@ PY if command -v gum >/dev/null 2>&1; then return 0 fi - + if command -v apt >/dev/null 2>&1; then mkdir -p /etc/apt/keyrings curl -fsSL https://repo.charm.sh/apt/gpg.key | gpg --dearmor -o /etc/apt/keyrings/charm.gpg @@ -11528,7 +11528,7 @@ REPO } - + change_model() { send_stats "Change model" @@ -11765,7 +11765,7 @@ PYTHON_EOF install_gum install gum - + # If gum does not exist, it will be downgraded to the original manual input process. if ! command -v gum >/dev/null 2>&1 || ! gum --version >/dev/null 2>&1; then echo "---Model Management ---" @@ -12085,7 +12085,7 @@ PYTHON_EOF - + install_plugin() { send_stats "Plug-in management" while true; do @@ -12777,7 +12777,7 @@ PY mkdir -p "$backup_root" local tmp_payload=$(mktemp -d) || return 1 local workspaces_json=$(openclaw_get_all_agent_workspaces) - python3 -c "import json, sys, os, shutil; + python3 -c "import json, sys, os, shutil; workspaces = json.loads(sys.argv[1]); tmp_payload = sys.argv[2] for item in workspaces: aid = item['id']; ws = item['ws'] @@ -14447,9 +14447,9 @@ PY local ask="$2" local fallback="$3" local approvals_file="$HOME/.openclaw/exec-approvals.json" - + mkdir -p "$HOME/.openclaw" - + # Generate JSON and write via openclaw approvals set --stdin (preferred) # If the CLI does not support it, it will fall back to writing the file directly. local json_payload @@ -14472,7 +14472,7 @@ data["defaults"]["askFallback"] = sys.argv[4] data["defaults"]["autoAllowSkills"] = True print(json.dumps(data, indent=2)) ' "$approvals_file" "$sec" "$ask" "$fallback") - + if openclaw_has_command openclaw && echo "$json_payload" | openclaw approvals set --stdin >/dev/null 2>&1; then return 0 fi @@ -14512,7 +14512,7 @@ print(json.dumps(data, indent=2)) echo "Exec limit: ${current_sec:-(unset)}" echo "Approval prompt: ${current_ask:-(unset)}" echo "Privilege elevation switch: ${current_elevated:-(unset)}" - + echo -e "\n${gl_huang}[Underlying Exec Approvals status]${gl_bai}" if openclaw_has_command openclaw; then local approvals_json @@ -14563,7 +14563,7 @@ except Exception: openclaw_permission_apply_standard() { send_stats "OpenClaw Permissions - Standard Security Mode" openclaw_permission_require_openclaw || return 1 - + echo "Configuring application layer policy..." openclaw config set tools.profile coding >/dev/null 2>&1 openclaw config set tools.exec.security allowlist >/dev/null 2>&1 @@ -14571,10 +14571,10 @@ except Exception: openclaw config set tools.elevated.enabled false >/dev/null 2>&1 openclaw config set tools.exec.strictInlineEval true >/dev/null 2>&1 # 拦截危险的内联代码 openclaw config unset commands.bash >/dev/null 2>&1 # 废弃旧版参数 - + echo "Configuring host approval interception..." openclaw_permission_update_exec_approvals "allowlist" "on-miss" "deny" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ Switched to standard safety mode (all dangerous commands will ask for your approval through UI/TG)${gl_bai}" } @@ -14582,17 +14582,17 @@ except Exception: openclaw_permission_apply_developer() { send_stats "OpenClaw Permissions - Development Enhanced Mode" openclaw_permission_require_openclaw || return 1 - + echo "Configuring application layer policy..." openclaw config set tools.profile coding >/dev/null 2>&1 openclaw config set tools.exec.security allowlist >/dev/null 2>&1 openclaw config set tools.exec.ask on-miss >/dev/null 2>&1 openclaw config set tools.elevated.enabled true >/dev/null 2>&1 # 允许智能体申请提权 openclaw config set tools.exec.strictInlineEval false >/dev/null 2>&1 - + echo "Configuring host approval interception..." openclaw_permission_update_exec_approvals "allowlist" "on-miss" "deny" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ Switched to development enhancement mode (privilege escalation is allowed, but common dangerous commands still require approval)${gl_bai}" } @@ -14600,18 +14600,18 @@ except Exception: openclaw_permission_apply_full() { send_stats "OpenClaw Permissions - Fully Open Mode" openclaw_permission_require_openclaw || return 1 - + echo "Configuring application layer policy..." openclaw config set tools.profile full >/dev/null 2>&1 openclaw config set tools.exec.security full >/dev/null 2>&1 openclaw config set tools.exec.ask off >/dev/null 2>&1 openclaw config set tools.elevated.enabled true >/dev/null 2>&1 openclaw config set tools.exec.strictInlineEval false >/dev/null 2>&1 - + echo "Disintegrating host interception defense..." # The full and off here will completely bypass the exec approval system of the underlying host. openclaw_permission_update_exec_approvals "full" "off" "full" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ Has been switched to fully open mode (Warning: All host command interceptions have expired, and the agent has the highest permissions)${gl_bai}" } @@ -14619,14 +14619,14 @@ except Exception: openclaw_permission_restore_official_defaults() { send_stats "OpenClaw permissions-restore official default" openclaw_permission_require_openclaw || return 1 - + echo "Clean application layer force coverage..." openclaw config unset tools.profile >/dev/null 2>&1 openclaw config unset tools.exec.security >/dev/null 2>&1 openclaw config unset tools.exec.ask >/dev/null 2>&1 openclaw config unset tools.elevated.enabled >/dev/null 2>&1 openclaw config unset tools.exec.strictInlineEval >/dev/null 2>&1 - + echo "Clean host interception configuration..." # Prioritize clearing the approval configuration through the CLI, and fall back to directly deleting the file. if echo '{"version":1,"defaults":{}}' | openclaw approvals set --stdin >/dev/null 2>&1; then @@ -14634,7 +14634,7 @@ except Exception: else rm -f "$HOME/.openclaw/exec-approvals.json" fi - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ Reverted to OpenClaw official security sandbox defense mechanism${gl_bai}" } @@ -15513,7 +15513,7 @@ while true; do echo -e "${gl_kjlan}1. ${color1}Pagoda panel official version${gl_kjlan}2. ${color2}aaPanel Pagoda International Version" echo -e "${gl_kjlan}3. ${color3}1Panel new generation management panel${gl_kjlan}4. ${color4}NginxProxyManager visualization panel" - echo -e "${gl_kjlan}5. ${color5}OpenList multi-store file list program${gl_kjlan}6. ${color6}Ubuntu Remote Desktop Web Version" + echo -e "${gl_kjlan}5. ${color5}OpenList multi-store file list program${gl_kjlan}6. ${color6}Ubuntu Remote Desktop Web Edition" echo -e "${gl_kjlan}7. ${color7}Nezha Probe VPS Monitoring Panel${gl_kjlan}8. ${color8}QB offline BT magnetic download panel" echo -e "${gl_kjlan}9. ${color9}Poste.io mail server program${gl_kjlan}10. ${color10}RocketChat multi-person online chat system" echo -e "${gl_kjlan}-------------------------" @@ -15579,6 +15579,7 @@ while true; do echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}111. ${color111}Multi-format file conversion tool${gl_kjlan}112. ${color112}Lucky large intranet penetration tool" echo -e "${gl_kjlan}113. ${color113}Firefox browser${gl_kjlan}114. ${color114}OpenClaw bot management tool${gl_huang}★${gl_bai}" + echo -e "${gl_kjlan}115. ${color115}Hermes robot management tool${gl_huang}★${gl_bai}" echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}Third-party application list" echo -e "${gl_kjlan}Want your app to appear here? Check out the developer guide:${gl_huang}https://dev.kejilion.sh/${gl_bai}" @@ -17622,7 +17623,7 @@ while true; do } - local docker_describe="Is a lightweight, high-performance music streaming server" + local docker_describe="It is a lightweight, high-performance music streaming server" local docker_url="Official website introduction: https://www.navidrome.org/" local docker_use="" local docker_passwd="" @@ -18206,7 +18207,7 @@ while true; do } - local docker_describe="A program for watching movies and live broadcasts together remotely. It provides simultaneous viewing, live broadcast, chat and other functions" + local docker_describe="A program to watch movies and live broadcasts together remotely. It provides simultaneous viewing, live broadcast, chat and other functions" local docker_url="Official website introduction:${gh_https_url}github.com/synctv-org/synctv" local docker_use="echo \"Initial account and password: root. Please change the login password in time after logging in\"" local docker_passwd="" @@ -19246,6 +19247,9 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ moltbot_menu ;; + 115|hermes) + bash <(curl -sL ${gh_proxy}raw.githubusercontent.com/kejilion/sh/main/hermes_manager.sh) + ;; b) clear @@ -19269,7 +19273,7 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ ssh-keygen -f "/root/.ssh/known_hosts" -R "$remote_ip" sleep 2 # 添加等待时间 scp -P "$TARGET_PORT" -o StrictHostKeyChecking=no "$latest_tar" "root@$remote_ip:/" - echo "文件已传送至远程服务器/根目录。" + echo "File transferred to remote server/root directory." else echo "The file to be transferred was not found." fi @@ -19287,7 +19291,7 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ r) root_use send_stats "Restore all apps" - echo "Available application backups" + echo "Available app backups" echo "-------------------------" ls -lt /app*.gz | awk '{print $NF}' echo "" @@ -19350,7 +19354,7 @@ linux_work() { echo -e "Backend workspace" echo -e "The system will provide you with a workspace that can run permanently in the background, which you can use to perform long-term tasks." echo -e "Even if you disconnect SSH, the tasks in the workspace will not be interrupted, and the tasks will remain in the background." - echo -e "${gl_huang}hint:${gl_bai}进入工作区后使用Ctrl+b再单独按d,退出工作区!" + echo -e "${gl_huang}hint:${gl_bai}After entering the workspace, use Ctrl+b and then press d alone to exit the workspace!" echo -e "${gl_kjlan}------------------------" echo "List of currently existing workspaces" echo -e "${gl_kjlan}------------------------" @@ -20516,7 +20520,7 @@ EOF echo "------------------------" echo "Europe" echo "11. London, UK time 12. Paris, France time" - echo "13. 德国柏林时间 14. 俄罗斯莫斯科时间" + echo "13. Berlin, Germany time 14. Moscow, Russia time" echo "15. Utracht Time, Netherlands 16. Madrid Time, Spain" echo "------------------------" echo "America" @@ -20780,7 +20784,7 @@ EOF echo -e "${gl_lv}The currently set inbound traffic limit threshold is:${gl_huang}${rx_threshold_gb}${gl_lv}G${gl_bai}" echo -e "${gl_lv}The currently set outbound traffic limiting threshold is:${gl_huang}${tx_threshold_gb}${gl_lv}GB${gl_bai}" else - echo -e "${gl_hui}The current limiting shutdown function is not currently enabled${gl_bai}" + echo -e "${gl_hui}Current limiting shutdown function is not currently enabled${gl_bai}" fi echo @@ -20992,7 +20996,7 @@ EOF echo "One-stop system tuning" echo "------------------------------------------------" echo "The following content will be operated and optimized" - echo "1. Optimize the system update source and update the system to the latest" + echo "1. 优化系统更新源,更新系统到最新" echo "2. Clean up system junk files" echo -e "3. Set up virtual memory${gl_huang}1G${gl_bai}" echo -e "4. Set the SSH port number to${gl_huang}5522${gl_bai}" @@ -21398,7 +21402,7 @@ run_commands_on_servers() { local username=${SERVER_ARRAY[i+3]} local password=${SERVER_ARRAY[i+4]} echo - echo -e "${gl_huang}Connect to$name ($hostname)...${gl_bai}" + echo -e "${gl_huang}connect to$name ($hostname)...${gl_bai}" # sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$hostname" -p "$port" "$1" sshpass -p "$password" ssh -t -o StrictHostKeyChecking=no "$username@$hostname" -p "$port" "$1" done @@ -21830,7 +21834,7 @@ done k_info() { -send_stats "k command reference examples" +send_stats "k command reference use case" echo "-------------------" echo "Video introduction: https://www.bilibili.com/video/BV1ib421E7it?t=0.1" echo "The following is a reference use case for the k command:" diff --git a/hermes_manager.sh b/hermes_manager.sh index b243a0d32..7f7d2e13f 100644 --- a/hermes_manager.sh +++ b/hermes_manager.sh @@ -1,501 +1,150 @@ - 1|<<<<<<< HEAD - 2|#!/bin/bash - 3|# Hermes Agent 终端管理脚本 (轻量版) - 4|# 设计哲学:极简、直观、调用原生功能 - 5| - 6|# 颜色定义 - 7|RED='\033[0;31m' - 8|GREEN='\033[0;32m' - 9|YELLOW='\033[1;33m' - 10|CYAN='\033[0;36m' - 11|NC='\033[0m' - 12| - 13|# 确保 hermes 命令可用 (处理环境变量未加载的情况) - 14|if ! command -v hermes >/dev/null 2>&1; then - 15| if [ -d "$HOME/.hermes/hermes-agent/venv/bin" ]; then - 16| export PATH="$HOME/.hermes/hermes-agent/venv/bin:$PATH" - 17| fi - 18|fi - 19| - 20|# 检查是否安装 - 21|check_installed() { - 22| if command -v hermes >/dev/null 2>&1; then return 0; else return 1; fi - 23|} - 24| - 25|# 获取版本号 - 26|get_version() { - 27| if check_installed; then - 28| hermes --version | head -n 1 - 29| fi - 30|} - 31| - 32|# 获取网关状态 - 33|get_gateway_status() { - 34| if check_installed; then - 35| # 匹配后台 gateway 进程或 systemd 服务 - 36| if pgrep -f "hermes_cli.main gateway" > /dev/null || pgrep -f "hermes gateway run" > /dev/null || pgrep -f "hermes-gateway" > /dev/null; then - 37| echo -e "${GREEN}运行中${NC}" - 38| else - 39| echo -e "${RED}已停止${NC}" - 40| fi - 41| else - 42| echo -e "${RED}未安装${NC}" - 43| fi - 44|} - 45| - 46|# 主菜单UI - 47|show_menu() { - 48| clear - 49| echo -e "${CYAN}=================================================${NC}" - 50| echo -e "${YELLOW} Hermes Agent 终端管理工具 ${NC}" - 51| echo -e "${CYAN}=================================================${NC}" - 52| echo -e " 运行状态 : $(get_gateway_status)" - 53| echo -e " 当前版本 : $(get_version)" - 54| echo -e "${CYAN}-------------------------------------------------${NC}" - 55| echo -e "${GREEN}1.${NC} 安装 Hermes Agent" - 56| echo -e "${GREEN}2.${NC} 启动 Gateway (消息网关/后台服务)" - 57| echo -e "${GREEN}3.${NC} 停止 Gateway" - 58| echo -e "${GREEN}4.${NC} API/模型管理 (提供商与模型切换)" - 59| echo -e "${GREEN}5.${NC} 启动终端对话UI (Interactive Chat)" - 60| echo -e "${GREEN}6.${NC} 运行初始化配置向导 (Setup Wizard)" - 61| echo -e "${GREEN}7.${NC} 检查并更新 Hermes" - 62| echo -e "${GREEN}8.${NC} 卸载 Hermes" - 63| echo -e "${GREEN}0.${NC} 退出" - 64| echo -e "${CYAN}=================================================${NC}" - 65| if ! read -p " 请输入数字 [0-8]: " choice; then - 66| echo -e "\n${GREEN}退出脚本。${NC}" - 67| exit 0 - 68| fi - 69| echo "" - 70| - 71| case $choice in - 72| 1) - 73| echo -e "${YELLOW}开始安装 Hermes Agent...${NC}" - 74| curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash - 75| source ~/.bashrc - 76| hermes gateway install - 77| hermes gateway start - 78| - 79| ;; - 80| 2) - 81| if check_installed; then - 82| echo -e "${YELLOW}正在启动 Gateway...${NC}" - 83| hermes gateway stop - 84| hermes gateway start - 85| else echo -e "${RED}请先安装 Hermes。${NC}"; fi - 86| ;; - 87| 3) - 88| if check_installed; then - 89| echo -e "${YELLOW}正在停止 Gateway...${NC}" - 90| hermes gateway stop - 91| else echo -e "${RED}请先安装 Hermes。${NC}"; fi - 92| ;; - 93| 4) - 94| if check_installed; then - 95| echo -e "${YELLOW}进入模型配置向导...${NC}" - 96| hermes model - 97| else echo -e "${RED}请先安装 Hermes。${NC}"; fi - 98| ;; - 99| 5) - 100| if check_installed; then - 101| echo -e "${YELLOW}即将进入交互式终端,输入 /exit 即可退出返回。${NC}" - 102| sleep 1 - 103| hermes - 104| else echo -e "${RED}请先安装 Hermes。${NC}"; fi - 105| ;; - 106| 6) - 107| if check_installed; then - 108| echo -e "${YELLOW}正在启动初始化配置向导...${NC}" - 109| hermes setup - 110| else echo -e "${RED}请先安装 Hermes。${NC}"; fi - 111| ;; - 112| 7) - 113| if check_installed; then - 114| echo -e "${YELLOW}正在检查更新...${NC}" - 115| hermes update - 116| else echo -e "${RED}请先安装 Hermes。${NC}"; fi - 117| ;; - 118| 8) - 119| if check_installed; then - 120| read -p "确定要卸载 Hermes 吗?所有数据将被清除。(y/N): " confirm - 121| if [[ "$confirm" =~ ^[Yy]$ ]]; then - 122| hermes uninstall - 123| else echo "已取消。"; fi - 124| else echo -e "${RED}请先安装 Hermes。${NC}"; fi - 125| ;; - 126| 0) - 127| echo -e "${GREEN}感谢使用,再见!${NC}" - 128| exit 0 - 129| ;; - 130| *) - 131| echo -e "${RED}输入错误,请重新选择。${NC}" - 132| ;; - 133| esac - 134| echo "" - 135| read -p "按回车键返回主菜单..." - 136|} - 137| - 138|# 主循环 - 139|while true; do - 140| show_menu - 141|done - 142|======= - 143| 1|#!/bin/bash - 144| 2|# Hermes Agent 终端管理脚本 v2.1 - 145| 3|# 借鉴 OpenClaw 管理模块,适配 Hermes Agent 配置体系 - 146| 4|# 设计哲学:极简、直观、Python yaml 安全读写(不依赖 yq) - 147| 5| - 148| 6|# 颜色定义 - 149| 7|RED='\033[0;31m' - 150| 8|GREEN='\033[0;32m' - 151| 9|YELLOW='\033[1;33m' - 152| 10|CYAN='\033[0;36m' - 153| 11|PURPLE='\033[0;35m' - 154| 12|DIM='\033[2m' - 155| 13|NC='\033[0m' - 156| 14| - 157| 15|# 确保 hermes 命令可用 (处理环境变量未加载的情况) - 158| 16|if ! command -v hermes >/dev/null 2>&1; then - 159| 17| if [ -d "$HOME/.hermes/hermes-agent/venv/bin" ]; then - 160| 18| export PATH="$HOME/.hermes/hermes-agent/venv/bin:$PATH" - 161| 19| fi - 162| 20|fi - 163| 21| - 164| 22|# 配置文件路径 - 165| 23|HERMES_CONFIG="${HOME}/.hermes/config.yaml" - 166| 24| - 167| 25|# ============================================================ - 168| 26|# 通用工具函数 - 169| 27|# ============================================================ - 170| 28| - 171| 29|check_installed() { - 172| 30| if command -v hermes >/dev/null 2>&1; then return 0; else return 1; fi - 173| 31|} - 174| 32| - 175| 33|get_version() { - 176| 34| if check_installed; then - 177| 35| hermes --version 2>/dev/null | head -n 1 - 178| 36| fi - 179| 37|} - 180| 38| - 181| 39|get_gateway_status() { - 182| 40| if check_installed; then - 183| 41| if pgrep -f "hermes_cli.main gateway" > /dev/null || pgrep -f "hermes gateway run" > /dev/null || pgrep -f "hermes-gateway" > /dev/null; then - 184| 42| echo -e "${GREEN}运行中${NC}" - 185| 43| else - 186| 44| echo -e "${RED}已停止${NC}" - 187| 45| fi - 188| 46| else - 189| 47| echo -e "${RED}未安装${NC}" - 190| 48| fi - 191| 49|} - 192| 50| - 193| 51|# 获取当前模型 - 194| 52|get_current_model() { - 195| 53| if [ ! -f "$HERMES_CONFIG" ]; then echo -e "${DIM}(未知)${NC}"; return; fi - 196| 54| python3 - "$HERMES_CONFIG" <<'PY' - 197| 55|import sys, yaml - 198| 56|with open(sys.argv[1], 'r') as f: - 199| 57| cfg = yaml.safe_load(f) - 200| 58|m = cfg.get('model', {}) - 201| 59|default = m.get('default', '') if isinstance(m, dict) else '' - 202| 60|if default: - 203| 61| print(f'\033[0;32m{default}\033[0m') - 204| 62|else: - 205| 63| print('\033[2m(未设置)\033[0m') - 206| 64|PY - 207| 65|} - 208| 66| - 209| 67|# 检查 python3 + yaml 可用 - 210| 68|ensure_python_yaml() { - 211| 69| if ! python3 -c "import yaml" 2>/dev/null; then - 212| 70| pip3 install pyyaml -q 2>/dev/null || pip install pyyaml -q 2>/dev/null - 213| 71| fi - 214| 72|} - 215| 73| - 216| 74|# 安装 jq(若缺失) - 217| 75|ensure_jq() { - 218| 76| if ! command -v jq >/dev/null 2>&1; then - 219| 77| echo -e "${YELLOW}正在安装 jq...${NC}" - 220| 78| if command -v apt >/dev/null 2>&1; then - 221| 79| apt update -qq && apt install -y -qq jq - 222| 80| elif command -v dnf >/dev/null 2>&1; then - 223| 81| dnf install -y jq - 224| 82| elif command -v yum >/dev/null 2>&1; then - 225| 83| yum install -y jq - 226| 84| fi - 227| 85| fi - 228| 86|} - 229| 87| - 230| 88|# 用 Python 读取 custom_providers,输出 JSON 数组 - 231| 89|read_providers_json() { - 232| 90| ensure_python_yaml - 233| 91| python3 - "$HERMES_CONFIG" <<'PY' - 234| 92|import sys, json, yaml - 235| 93|with open(sys.argv[1], 'r') as f: - 236| 94| cfg = yaml.safe_load(f) - 237| 95|providers = cfg.get('custom_providers', []) - 238| 96|json.dump(providers, sys.stdout, ensure_ascii=False) - 239| 97|PY - 240| 98|} - 241| 99| - 242| 100|# 重启 Gateway - 243| 101|restart_gateway() { - 244| 102| echo -e "${YELLOW}正在重启 Gateway...${NC}" - 245| 103| hermes gateway stop 2>/dev/null - 246| 104| sleep 1 - 247| 105| systemctl --user start hermes-gateway 2>/dev/null - 248| 106| hermes gateway start 2>/dev/null - 249| 107| echo -e "${GREEN}Gateway 已重启${NC}" - 250| 108|} - 251| 109| - 252| 110|# ============================================================ - 253| 111|# API 管理子菜单 - 254| 112|# ============================================================ - 255| 113| - 256| 114|hermes_api_list() { - 257| 115| echo "" - 258| 116| echo -e "${CYAN}--- 已配置 API 列表 ---${NC}" - 259| 117| - 260| 118| if [ ! -f "$HERMES_CONFIG" ]; then - 261| 119| echo -e "${RED}未找到配置文件: $HERMES_CONFIG${NC}" - 262| 120| return 1 - 263| 121| fi - 264| 122| - 265| 123| python3 - "$HERMES_CONFIG" <<'PY' - 266| 124|import sys, yaml, json, time, urllib.request - 267| 125| - 268| 126|GREEN = '\033[0;32m' - 269| 127|YELLOW = '\033[1;33m' - 270| 128|RED = '\033[0;31m' - 271| 129|DIM = '\033[2m' - 272| 130|NC = '\033[0m' - 273| 131| - 274| 132|with open(sys.argv[1], 'r') as f: - 275| 133| cfg = yaml.safe_load(f) - 276| 134| - 277| 135|providers = cfg.get('custom_providers', []) - 278| 136|if not providers: - 279| 137| print(f'{DIM}当前未配置任何 API provider。{NC}') - 280| 138| sys.exit(0) - 281| 139| - 282| 140|for idx, p in enumerate(providers, start=1): - 283| 141| name = p.get('name', '-') - 284| 142| base_url = p.get('base_url', '-') - 285| 143| model = p.get('model', '-') - 286| 144| api_key = p.get('api_key', '') - 287| 145| masked_key = f"{api_key[:8]}****" if len(str(api_key)) > 8 else "****" - 288| 146| - 289| 147| # Ping 延迟 - 290| 148| latency_raw = "未检测" - 291| 149| latency_level = "unchecked" - 292| 150| if base_url and base_url != '-' and api_key: - 293| 151| try: - 294| 152| url = base_url.rstrip('/') + '/models' - 295| 153| req = urllib.request.Request(url, headers={ - 296| 154| 'Authorization': f'Bearer {api_key}', - 297| 155| 'User-Agent': 'Hermes-Manager/1.0', - 298| 156| }) - 299| 157| start = time.perf_counter() - 300| 158| with urllib.request.urlopen(req, timeout=4) as resp: - 301| 159| resp.read(2048) - 302| 160| ms = int((time.perf_counter() - start) * 1000) - 303| 161| latency_raw = f"{ms}ms" - 304| 162| latency_level = 'low' if ms <= 800 else ('medium' if ms <= 2000 else 'high') - 305| 163| except Exception: - 306| 164| latency_raw = "不可用" - 307| 165| latency_level = "unavailable" - 308| 166| - 309| 167| if latency_level == 'low': latency_color = GREEN - 310| 168| elif latency_level == 'medium': latency_color = YELLOW - 311| 169| elif latency_level == 'unavailable': latency_color = RED - 312| 170| else: latency_color = DIM - 313| 171| - 314| 172| print(f" [{idx}] {name}") - 315| 173| print(f" URL: {base_url} Key: {masked_key} 模型: {YELLOW}{model}{NC} 延迟: {latency_color}{latency_raw}{NC}") - 316| 174| - 317| 175|PY - 318| 176|} - 319| 177| - 320| 178|# 添加 API Provider - 321| 179|hermes_api_add() { - 322| 180| echo "" - 323| 181| echo -e "${CYAN}=== 交互式添加 Hermes API Provider ===${NC}" - 324| 182| - 325| 183| # Provider 名称 - 326| 184| read -erp "请输入 Provider 名称 (如: deepseek): " provider_name - 327| 185| while [[ -z "$provider_name" ]]; do - 328| 186| echo -e "${RED}Provider 名称不能为空${NC}" - 329| 187| read -erp "请输入 Provider 名称: " provider_name - 330| 188| done - 331| 189| - 332| 190| # Base URL - 333| 191| read -erp "请输入 Base URL (如: https://api.deepseek.com/v1): " base_url - 334| 192| while [[ -z "$base_url" ]]; do - 335| 193| echo -e "${RED}Base URL 不能为空${NC}" - 336| 194| read -erp "请输入 Base URL: " base_url - 337| 195| done - 338| 196| base_url="${base_url%/}" - 339| 197| - 340| 198| # API Key - 341| 199| stty -echo - 342| 200| read -r -p "请输入 API Key (输入不显示): " api_key - 343| 201| stty echo - 344| 202| echo - 345| 203| while [[ -z "$api_key" ]]; do - 346| 204| echo -e "${RED}API Key 不能为空${NC}" - 347| 205| stty -echo - 348| 206| read -r -p "请输入 API Key: " api_key - 349| 207| stty echo - 350| 208| echo - 351| 209| done - 352| 210| - 353| 211| # 获取模型列表 - 354| 212| echo -e "${YELLOW}正在获取可用模型列表...${NC}" - 355| 213| models_json=$(curl -s -m 10 \ - 356| 214| -H "Authorization: Bearer *** \ - 357| 215| "${base_url}/models" 2>/dev/null) - 358| 216| - 359| 217| available_models="" - 360| 218| model_count=0 - 361| 219| model_list=() - 362| 220| if [[ -n "$models_json" ]]; then - 363| 221| ensure_jq - 364| 222| available_models=$(echo "$models_json" | jq -r '.data[]?.id // empty' 2>/dev/null | sort) - 365| 223| if [[ -n "$available_models" ]]; then - 366| 224| model_count=$(echo "$available_models" | wc -l | tr -d ' ') - 367| 225| echo -e "${GREEN}发现 ${model_count} 个可用模型:${NC}" - 368| 226| echo "--------------------------------" - 369| 227| i=1 - 370| 228| while read -r model; do - 371| 229| echo "[$i] $model" - 372| 230| model_list+=("$model") - 373| 231| ((i++)) - 374| 232| done <<< "$available_models" - 375| 233| echo "--------------------------------" - 376| 234| fi - 377| 235| fi - 378| 236| - 379| 237| # 如果获取失败,手动输入 - 380| 238| if [[ $model_count -eq 0 ]]; then - 381| 239| echo -e "${YELLOW}未能自动获取模型列表,请手动输入。${NC}" - 382| 240| read -erp "请输入默认 Model ID: " default_model - 383| 241| while [[ -z "$default_model" ]]; do - 384| 242| echo -e "${RED}Model ID 不能为空${NC}" - 385| 243| read -erp "请输入 Model ID: " default_model - 386| 244| done - 387| 245| else - 388| 246| # 选择默认模型 - 389| 247| echo - 390| 248| read -erp "请输入默认 Model ID (或序号,留空则使用第一个): " input_model - 391| 249| if [[ -z "$input_model" ]]; then - 392| 250| default_model=$(echo "$available_models" | head -1) - 393| 251| echo -e "使用第一个模型: ${GREEN}${default_model}${NC}" - 394| 252| elif [[ "$input_model" =~ ^[0-9]+$ ]] && [ "${#model_list[@]}" -gt 0 ] && [ "$input_model" -ge 1 ] && [ "$input_model" -le "${#model_list[@]}" ]; then - 395| 253| default_model="${model_list[$((input_model-1))]}" - 396| 254| echo -e "已选择模型: ${GREEN}${default_model}${NC}" - 397| 255| else - 398| 256| default_model="$input_model" - 399| 257| fi - 400| 258| fi - 401| 259| - 402| 260| # 确认信息 - 403| 261| echo - 404| 262| echo "====== 确认信息 ======" - 405| 263| echo "Provider : $provider_name" - 406| 264| echo "Base URL : $base_url" - 407| 265| echo "API Key : ${api_key:0:8}****" - 408| 266| echo "默认模型 : $default_model" - 409| 267| echo "======================" - 410| 268| - 411| 269| # 写入配置 - 412| 270| echo -e "${YELLOW}正在写入配置...${NC}" - 413| 271| - 414| 272| python3 - "$HERMES_CONFIG" "$provider_name" "$base_url" "$api_key" "$default_model" <<'PY' - 415| 273|import sys, yaml, shutil - 416| 274| - 417| 275|path = sys.argv[1] - 418| 276|name = sys.argv[2] - 419| 277|base_url = sys.argv[3] - 420| 278|api_key = sys.argv[4] - 421| 279|model = sys.argv[5] - 422| 280| - 423| 281|with open(path, 'r', encoding='utf-8') as f: - 424| 282| cfg = yaml.safe_load(f) - 425| 283| - 426| 284|providers = cfg.get('custom_providers', []) - 427| 285| - 428| 286|# 检查是否已存在同名 provider - 429| 287|existing_idx = None - 430| 288|for i, p in enumerate(providers): - 431| 289| if p.get('name') == name: - 432| 290| existing_idx = i - 433| 291| break - 434| 292| - 435| 293|new_provider = { - 436| 294| 'name': name, - 437| 295| 'base_url': base_url, - 438| 296| 'api_key': api_key, - 439| 297| 'model': model, - 440| 298|} - 441| 299| - 442| 300|if existing_idx is not None: - 443| 301| providers[existing_idx] = new_provider - 444| 302| print(f'已更新同名 provider: {name}') - 445| 303|else: - 446| 304| providers.append(new_provider) - 447| 305| print(f'已添加 provider: {name}') - 448| 306| - 449| 307|cfg['custom_providers'] = providers - 450| 308| - 451| 309|# 备份 - 452| 310|shutil.copy2(path, path + '.bak') - 453| 311| - 454| 312|with open(path, 'w', encoding='utf-8') as f: - 455| 313| yaml.dump(cfg, f, default_flow_style=False, allow_unicode=True, sort_keys=False) - 456| 314| - 457| 315|print('OK') - 458| 316|PY - 459| 317| - 460| 318| if [ $? -eq 0 ]; then - 461| 319| echo -e "${GREEN}已成功添加 provider: ${provider_name}${NC}" - 462| 320| - 463| 321| # 询问是否切换为当前使用 - 464| 322| echo - 465| 323| read -erp "是否立即切换到该 provider?(y/N): " switch_now - 466| 324| if [[ "$switch_now" =~ ^[Yy]$ ]]; then - 467| 325| hermes_switch_to_provider "$provider_name" - 468| 326| fi - 469| 327| else - 470| 328| echo -e "${RED}配置写入失败${NC}" - 471| 329| fi - 472| 330|} - 473| 331| - 474| 332|# 切换到指定 provider - 475| 333|hermes_switch_to_provider() { - 476| 334| local target_name="$1" - 477| 335| - 478| 336| if [ -z "$target_name" ]; then - 479| 337| read -erp "请输入要切换的 Provider 名称: " target_name - 480| 338| fi - 481| 339| - 482| 340| python3 - "$HERMES_CONFIG" "$target_name" <<'PY' - 483| 341|import sys, yaml, shutil - 484| 342| - 485| 343|path = sys.argv[1] - 486| 344|target = sys.argv[2] - 487| 345| - 488| 346|with open(path, 'r', encoding='utf-8') as f: - 489| 347| cfg = yaml.safe_load(f) - 490| 348| - 491| 349|providers = cfg.get('custom_providers', []) - 492| 350|target_p = None - 493| 351|for p in providers: - 494| 352| if p.get('name') == target: - 495| 353| target_p = p - 496| 354| break - 497| 355| - 498| 356|if target_p is None: - 499| 357| print(f'ERROR: 未找到 provider: {target}') - 500| 358| sys.exit(1) - 501| \ No newline at end of file +#!/bin/bash +# Hermes Agent 终端管理脚本 (轻量版) +# 设计哲学:极简、直观、调用原生功能 + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' + +# 确保 hermes 命令可用 (处理环境变量未加载的情况) +if ! command -v hermes >/dev/null 2>&1; then + if [ -d "$HOME/.hermes/hermes-agent/venv/bin" ]; then + export PATH="$HOME/.hermes/hermes-agent/venv/bin:$PATH" + fi +fi + +# 检查是否安装 +check_installed() { + if command -v hermes >/dev/null 2>&1; then return 0; else return 1; fi +} + +# 获取版本号 +get_version() { + if check_installed; then + hermes --version | head -n 1 + fi +} + +# 获取网关状态 +get_gateway_status() { + if check_installed; then + # 匹配后台 gateway 进程或 systemd 服务 + if pgrep -f "hermes_cli.main gateway" > /dev/null || pgrep -f "hermes gateway run" > /dev/null || pgrep -f "hermes-gateway" > /dev/null; then + echo -e "${GREEN}运行中${NC}" + else + echo -e "${RED}已停止${NC}" + fi + else + echo -e "${RED}未安装${NC}" + fi +} + + +refresh_hermes_path() { + if ! command -v hermes >/dev/null 2>&1; then + if [ -d "$HOME/.hermes/hermes-agent/venv/bin" ]; then + export PATH="$HOME/.hermes/hermes-agent/venv/bin:$PATH" + fi + fi +} + + +# 主菜单UI +show_menu() { + clear + echo -e "${CYAN}=================================================${NC}" + echo -e "${YELLOW} Hermes Agent 终端管理工具 ${NC}" + echo -e "${CYAN}=================================================${NC}" + echo -e " 运行状态 : $(get_gateway_status)" + echo -e " 当前版本 : $(get_version)" + echo -e "${CYAN}-------------------------------------------------${NC}" + echo -e "${GREEN}1.${NC} 安装 Hermes Agent" + echo -e "${GREEN}2.${NC} 启动 Gateway (消息网关/后台服务)" + echo -e "${GREEN}3.${NC} 停止 Gateway" + echo -e "${GREEN}4.${NC} API/模型管理 (提供商与模型切换)" + echo -e "${GREEN}5.${NC} 启动终端对话UI (Interactive Chat)" + echo -e "${GREEN}6.${NC} 运行初始化配置向导 (Setup Wizard)" + echo -e "${GREEN}7.${NC} 检查并更新 Hermes" + echo -e "${GREEN}8.${NC} 卸载 Hermes" + echo -e "${GREEN}0.${NC} 退出" + echo -e "${CYAN}=================================================${NC}" + if ! read -p " 请输入数字 [0-8]: " choice; then + echo -e "\n${GREEN}退出脚本。${NC}" + exit 0 + fi + echo "" + + case $choice in + 1) + echo -e "${YELLOW}开始安装 Hermes Agent...${NC}" + curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash + refresh_hermes_path + hermes gateway install + hermes gateway start + ;; + 2) + if check_installed; then + echo -e "${YELLOW}正在启动 Gateway...${NC}" + systemctl --user start hermes-gateway + hermes gateway stop + hermes gateway start + else echo -e "${RED}请先安装 Hermes。${NC}"; fi + ;; + 3) + if check_installed; then + echo -e "${YELLOW}正在停止 Gateway...${NC}" + hermes gateway stop + else echo -e "${RED}请先安装 Hermes。${NC}"; fi + ;; + 4) + if check_installed; then + echo -e "${YELLOW}进入模型配置向导...${NC}" + hermes model + else echo -e "${RED}请先安装 Hermes。${NC}"; fi + ;; + 5) + if check_installed; then + echo -e "${YELLOW}即将进入交互式终端,输入 /exit 即可退出返回。${NC}" + sleep 1 + hermes + else echo -e "${RED}请先安装 Hermes。${NC}"; fi + ;; + 6) + if check_installed; then + echo -e "${YELLOW}正在启动初始化配置向导...${NC}" + hermes setup + else echo -e "${RED}请先安装 Hermes。${NC}"; fi + ;; + 7) + if check_installed; then + echo -e "${YELLOW}正在检查更新...${NC}" + hermes update + else echo -e "${RED}请先安装 Hermes。${NC}"; fi + ;; + 8) + if check_installed; then + read -p "确定要卸载 Hermes 吗?所有数据将被清除。(y/N): " confirm + if [[ "$confirm" =~ ^[Yy]$ ]]; then + hermes uninstall + else echo "已取消。"; fi + else echo -e "${RED}请先安装 Hermes。${NC}"; fi + ;; + 0) + echo -e "${GREEN}感谢使用,再见!${NC}" + exit 0 + ;; + *) + echo -e "${RED}输入错误,请重新选择。${NC}" + ;; + esac + echo "" + read -p "按回车键返回主菜单..." +} + +# 主循环 +while true; do + show_menu +done diff --git a/jp/kejilion.sh b/jp/kejilion.sh index a11669c59..d810764c3 100644 --- a/jp/kejilion.sh +++ b/jp/kejilion.sh @@ -1,5 +1,5 @@ #!/bin/bash -sh_v="4.4.9" +sh_v="4.4.10" gl_hui='\e[37m' @@ -260,7 +260,7 @@ remove() { fi for package in "$@"; do - echo -e "${gl_kjlan}アンインストールする$package...${gl_bai}" + echo -e "${gl_kjlan}アンインストール中$package...${gl_bai}" if command -v dnf &>/dev/null; then dnf remove -y "$package" elif command -v yum &>/dev/null; then @@ -1195,7 +1195,7 @@ iptables_panel() { ;; 15) - read -e -p "ブロックされている国コードを入力してください (CN US JP のように、複数の国コードをスペースで区切ることができます)。" country_code + read -e -p "ブロックされている国コードを入力してください (CN US JP のように、複数の国コードをスペースで区切ることができます):" country_code manage_country_rules block $country_code send_stats "国を許可する$country_codeIP" ;; @@ -2237,7 +2237,7 @@ web_security() { ;; 22) - send_stats "高負荷で5秒シールド可能" + send_stats "高負荷により5秒シールドが可能" echo -e "${gl_huang}Web サイトは 5 分ごとに自動的に検出します。高負荷を検出すると自動的にシールドが開き、低負荷を検出すると5秒間自動的にシールドが閉じます。${gl_bai}" echo "--------------" echo "CFパラメータを取得します。" @@ -2324,7 +2324,7 @@ check_nginx_compression() { # zstd がオンでコメントが解除されているかどうかを確認します (行全体が zstd on で始まります)。 if grep -qE '^\s*zstd\s+on;' "$CONFIG_FILE"; then - zstd_status="zstd圧縮が有効になっています" + zstd_status="zstd圧縮がオンになっています" else zstd_status="" fi @@ -2561,7 +2561,7 @@ check_docker_image_update() { # --- シナリオ A: GitHub (ghcr.io) 上のミラー --- # ウェアハウスのパスを抽出します (例: ghcr.io/onexru/oneimg -> onexru/oneimg) local repo_path=$(echo "$full_image_name" | sed 's/ghcr.io\///' | cut -d':' -f1) - # 注: ghcr.io の API は比較的複雑です。通常、最も早い方法は、GitHub リポジトリのリリースを確認することです + # 注: ghcr.io の API は比較的複雑です。通常、最も早い方法は、GitHub リポジトリのリリースを確認することです。 local api_url="https://api.github.com/repos/$repo_path/releases/latest" local remote_date=$(curl -s "$api_url" | jq -r '.published_at' 2>/dev/null) @@ -2893,7 +2893,7 @@ while true; do setup_docker_dir check_disk_space $app_size /home/docker while true; do - read -e -p "アプリケーションの外部サービス ポートを入力し、Enter キーを押して、それをデフォルトで使用します。${docker_port}ポート:" app_port + read -e -p "アプリケーションの外部サービス ポートを入力し、Enter キーを押してデフォルトで使用します。${docker_port}ポート:" app_port local app_port=${app_port:-${docker_port}} if ss -tuln | grep -q ":$app_port "; then @@ -3016,7 +3016,7 @@ docker_app_plus() { check_disk_space $app_size /home/docker while true; do - read -e -p "アプリケーションの外部サービス ポートを入力し、Enter キーを押して、それをデフォルトで使用します。${docker_port}ポート:" app_port + read -e -p "アプリケーションの外部サービス ポートを入力し、Enter キーを押してデフォルトで使用します。${docker_port}ポート:" app_port local app_port=${app_port:-${docker_port}} if ss -tuln | grep -q ":$app_port "; then @@ -3221,7 +3221,7 @@ f2b_sshd() { # 基本パラメータ設定: 禁止期間 (bantime)、時間枠 (findtime)、再試行回数 (maxretry) # 例証します: -# - /etc/fail2ban/jail.d/sshd.local への書き込みを優先します (デフォルトのjail設定をオーバーライドし、アップグレード時に失われにくくなります) +# - /etc/fail2ban/jail.d/sshd.local への書き込みを優先します (デフォルトのjail設定を上書きし、アップグレード時に失われにくくなります) # - Alpine で、jail 名が異なる場合でも、sshd.local と書き込みます。 Fail2Ban は、jail 名に従って一致します。 f2b_basic_config() { root_use @@ -3290,7 +3290,7 @@ f2b_edit_config() { [ -f "$cfg" ] || printf "[sshd]\n# bantime/findtime/maxretry\n" > "$cfg" nano "$cfg" - echo -e "${gl_lv}保存されました${gl_bai}、fail2ban をリロード中..." + echo -e "${gl_lv}保存されました${gl_bai}、fail2ban をリロードしています..." fail2ban-client reload >/dev/null 2>&1 || true } @@ -3752,7 +3752,7 @@ ldnmp_Proxy_backend_stream() { *) echo "無効な選択"; return 1 ;; esac - read -e -p "1 つ以上のバックエンド IP + ポートをスペースで区切って入力してください (例: 10.13.0.2:3306 10.13.0.3:3306)。" reverseproxy_port + read -e -p "1 つ以上のバックエンド IP + ポートをスペースで区切って入力してください (例: 10.13.0.2:3306 10.13.0.3:3306):" reverseproxy_port nginx_install_status cd /home && mkdir -p web/stream.d @@ -4415,7 +4415,7 @@ frps_panel() { 8) send_stats "IPアクセスをブロックする" - echo "ドメイン名アクセスを反転している場合は、この機能を使用して IP+ポート アクセスをブロックすることができ、より安全です。" + echo "ドメイン名アクセスを逆にしている場合は、この機能を使用して IP+ポート アクセスをブロックすることができ、より安全になります。" read -e -p "ブロックするポートを入力してください:" frps_port block_host_port "$frps_port" "$ipv4_address" ;; @@ -6160,7 +6160,7 @@ vm.vfs_cache_pressure = $VFS_PRESSURE # ──CPU/カーネルのスケジューリング── kernel.sched_autogroup_enabled = $SCHED_AUTOGROUP -$([ -f /proc/sys/kernel/numa_balancing ] && echo "kernel.numa_balancing = $NUMA" || echo "# uma_balancing はサポートされていません") +$([ -f /proc/sys/kernel/numa_balancing ] && echo "kernel.numa_balancing = $NUMA" || echo "# numa_balancing 不支持") # ──安全保護── net.ipv4.conf.all.rp_filter = 1 @@ -7213,7 +7213,7 @@ disk_manager() { send_stats "ハードディスク管理機能" while true; do clear - echo "ハードドライブのパーティション管理" + echo "ハードディスクのパーティション管理" echo -e "${gl_huang}この機能は内部テスト中であるため、運用環境では使用しないでください。${gl_bai}" echo "------------------------" list_partitions @@ -8318,7 +8318,7 @@ linux_docker() { echo -e "${gl_kjlan}5. ${gl_bai}Dockerネットワーク管理" echo -e "${gl_kjlan}6. ${gl_bai}Docker ボリューム管理" echo -e "${gl_kjlan}------------------------" - echo -e "${gl_kjlan}7. ${gl_bai}不要な Docker コンテナをクリーンアップし、ネットワーク データ ボリュームをミラーリングします" + echo -e "${gl_kjlan}7. ${gl_bai}不要な Docker コンテナをクリーンアップし、ネットワーク データ ボリュームをミラーリングします。" echo -e "${gl_kjlan}------------------------" echo -e "${gl_kjlan}8. ${gl_bai}Dockerソースを変更する" echo -e "${gl_kjlan}9. ${gl_bai}daemon.json ファイルを編集する" @@ -10568,7 +10568,7 @@ EOF local config_file config_file=$(openclaw_get_config_file) - # API プロトコルを自動的に検出/修正しなくなりました。ユーザー構成を維持します + # API プロトコルを自動的に検出/修正しなくなりました。ユーザー設定を維持します DETECTED_API="openai-completions" [[ -f "$config_file" ]] && cp "$config_file" "${config_file}.bak.$(date +%s)" @@ -10734,7 +10734,7 @@ EOF # 5. デフォルトのモデルを選択します echo - read -erp "デフォルトのモデル ID (またはシリアル番号。最初のものを使用する場合は空白のままにします) を入力してください。" input_model + read -erp "デフォルトのモデル ID (またはシリアル番号、最初のものを使用する場合は空白のままにしておきます) を入力してください:" input_model if [[ -z "$input_model" && -n "$available_models" ]]; then default_model=$(echo "$available_models" | head -1) @@ -10783,7 +10783,7 @@ EOF } - + openclaw_api_manage_list() { local config_file="${HOME}/.openclaw/openclaw.json" send_stats "OpenClaw API リスト" @@ -11124,7 +11124,7 @@ PY2 local rc=$? case "$rc" in 0) - echo "✅ 同期実行完了" + echo "✅ 同期実行が完了しました" start_gateway ;; 2) @@ -11140,7 +11140,7 @@ PY2 echo "❌ 同期に失敗しました: 上流モデルが空であるか、同期後に使用可能なモデルがありません" ;; *) - echo "❌ 同期に失敗しました: 構成ファイルの構造またはログ出力を確認してください。" + echo "❌ 同期に失敗しました: 設定ファイルの構造またはログ出力を確認してください。" ;; esac @@ -11171,7 +11171,7 @@ fix-openclaw-provider-protocol-interactive() { return 1 fi - echo "セットアップする API タイプを選択してください:" + echo "設定したい API タイプを選択してください:" echo "1. openai-completions" echo "2. openai-responses" read -erp "選択肢を入力してください (1/2):" proto_choice @@ -11450,7 +11450,7 @@ PY } openclaw_api_manage_menu() { - send_stats "OpenClaw APIの入り口" + send_stats "OpenClaw APIの入口" while true; do clear echo "=======================================" @@ -11500,7 +11500,7 @@ PY if command -v gum >/dev/null 2>&1; then return 0 fi - + if command -v apt >/dev/null 2>&1; then mkdir -p /etc/apt/keyrings curl -fsSL https://repo.charm.sh/apt/gpg.key | gpg --dearmor -o /etc/apt/keyrings/charm.gpg @@ -11528,7 +11528,7 @@ REPO } - + change_model() { send_stats "機種変更" @@ -11765,7 +11765,7 @@ PYTHON_EOF install_gum install gum - + # ガムが存在しない場合は、元の手入力プロセスにダウングレードされます。 if ! command -v gum >/dev/null 2>&1 || ! gum --version >/dev/null 2>&1; then echo "---モデル管理---" @@ -12085,7 +12085,7 @@ PYTHON_EOF - + install_plugin() { send_stats "プラグイン管理" while true; do @@ -12193,7 +12193,7 @@ PYTHON_EOF if openclaw plugins uninstall "$plugin_id"; then echo "✅ アンインストール済み:$plugin_id" else - echo "⚠️ アンインストールに失敗しました。プリインストールされたプラグインである可能性があります。以下を無効にするだけです。$plugin_id" + echo "⚠️ アンインストールに失敗しました。プリインストールされたプラグインである可能性があります。次の機能のみを無効にしてください。$plugin_id" fi sync_openclaw_plugin_denylist "$plugin_id" >/dev/null 2>&1 success_list="$success_list $plugin_id" @@ -12239,7 +12239,7 @@ PYTHON_EOF echo "bluebubbles # BlueBubbles で iMessage を完璧に送受信" echo "ヒマラヤ # 端末メール管理(IMAP/SMTP強力ツール)" echo "要約 # Web ページ/ポッドキャスト/YouTube ビデオ コンテンツのワンクリック要約" - echo "openhue # Philips Hue スマート照明シーンの制御" + echo "openhue # Philips Hue スマート照明シーンを制御する" echo "video-frames # ビデオフレーム抽出とショートクリップ編集 (ffmpeg ドライバー)" echo "openai-whisper # ローカル音声をテキストに変換 (オフラインのプライバシー保護)" echo "coding-agent # Claude Code/Codex などのプログラミング アシスタントを自動的に実行する" @@ -12591,7 +12591,7 @@ openclaw_json_get_bool() { break_end ;; 3) - read -e -p "WhatsApp で受信した接続コード (例: NYA99R2F) を入力してください (終了するには 0 を入力してください):" code + read -e -p "WhatsApp で受け取った接続コード (例: NYA99R2F) を入力してください (終了するには 0 を入力してください):" code if [ "$code" = "0" ]; then continue; fi if [ -z "$code" ]; then echo "エラー: 接続コードを空にすることはできません。"; sleep 1; continue; fi openclaw pairing approve whatsapp "$code" @@ -12777,7 +12777,7 @@ PY mkdir -p "$backup_root" local tmp_payload=$(mktemp -d) || return 1 local workspaces_json=$(openclaw_get_all_agent_workspaces) - python3 -c "import json, sys, os, shutil; + python3 -c "import json, sys, os, shutil; workspaces = json.loads(sys.argv[1]); tmp_payload = sys.argv[2] for item in workspaces: aid = item['id']; ws = item['ws'] @@ -13366,7 +13366,7 @@ for entry in data: first = False print("Agent: %s" % agent_id) backend = s.get("backend") or s.get("provider") or "-" - print("基本的なソリューション: %s" % backend) + print("基礎となるソリューション: %s" % backend) files = s.get("files", 0) chunks = s.get("chunks", 0) print("含まれるもの: %s ファイル / %s ブロック" % (files, chunks)) @@ -13685,7 +13685,7 @@ PY echo "考えられるトラフィック/ディスク使用量: 実際の状況によって異なります" fi echo "確認後、自動的にインストール/ダウンロード、構成の書き込み、インデックスの構築、ゲートウェイの再起動が行われます。" - echo "詳細オプション: config と入力して構成のみを書き込みます (インストールなし、ダウンロードなし、インデックス作成なし、再起動なし)。" + echo "詳細オプション: config を入力して構成のみを書き込みます (インストールなし、ダウンロードなし、インデックス作成なし、再起動なし)。" read -e -p "続行することを確認するには「yes」と入力します (デフォルトは N):" confirm_step case "$confirm_step" in yes|YES) @@ -13874,7 +13874,7 @@ EOF while true; do clear echo "=======================================" - echo "メモリソリューションの自動導入" + echo "メモリソリューションの自動展開" echo "=======================================" echo "1. QMD" echo "2. Local" @@ -14099,7 +14099,7 @@ EOF echo "書類:$file" echo "総行数:$total_lines" read -e -p "開始行を入力してください (Enter キーを押すとデフォルトで行の終わりになります)$default_linesわかりました):" start_line - read -e -p "表示する行数を入力してください (デフォルトでは Enter を押します)$default_lines): " count + read -e -p "表示する行数を入力してください (デフォルトでは Enter キーを押します)$default_lines): " count [ -z "$count" ] && count=$default_lines if [ -z "$start_line" ]; then if [ "$total_lines" -le "$count" ]; then @@ -14447,9 +14447,9 @@ PY local ask="$2" local fallback="$3" local approvals_file="$HOME/.openclaw/exec-approvals.json" - + mkdir -p "$HOME/.openclaw" - + # JSON を生成し、openclaw 承認セット --stdin 経由で書き込みます (推奨) # CLI がこれをサポートしていない場合は、ファイルの直接書き込みに戻ります。 local json_payload @@ -14472,7 +14472,7 @@ data["defaults"]["askFallback"] = sys.argv[4] data["defaults"]["autoAllowSkills"] = True print(json.dumps(data, indent=2)) ' "$approvals_file" "$sec" "$ask" "$fallback") - + if openclaw_has_command openclaw && echo "$json_payload" | openclaw approvals set --stdin >/dev/null 2>&1; then return 0 fi @@ -14507,12 +14507,12 @@ print(json.dumps(data, indent=2)) fi echo -e "現在の包括的なセキュリティ レベル:${current_mode}" echo "---------------------------------------" - echo -e "${gl_huang}[アプリケーション層ツールのポリシーステータス]${gl_bai}" + echo -e "${gl_huang}[アプリケーション層ツールのポリシーのステータス]${gl_bai}" echo "プロファイル (デフォルト): ${current_profile:-(未設定)}" echo "実行制限: ${current_sec:-(未設定)}" echo "承認プロンプト: ${current_ask:-(unset)}" echo "特権昇格スイッチ: ${current_elevated:-(unset)}" - + echo -e "\n${gl_huang}[基本的な幹部の承認ステータス]${gl_bai}" if openclaw_has_command openclaw; then local approvals_json @@ -14556,14 +14556,14 @@ except Exception: print("(設定ファイルの解析に失敗しました)") ' else - echo "(未構成。システムの組み込みセキュリティ ポリシーの使用が強制されます)" + echo "(未構成、システムの組み込みセキュリティ ポリシーの使用が強制されます)" fi } openclaw_permission_apply_standard() { send_stats "OpenClaw 権限 - 標準セキュリティ モード" openclaw_permission_require_openclaw || return 1 - + echo "アプリケーション層ポリシーを構成しています..." openclaw config set tools.profile coding >/dev/null 2>&1 openclaw config set tools.exec.security allowlist >/dev/null 2>&1 @@ -14571,10 +14571,10 @@ except Exception: openclaw config set tools.elevated.enabled false >/dev/null 2>&1 openclaw config set tools.exec.strictInlineEval true >/dev/null 2>&1 # 拦截危险的内联代码 openclaw config unset commands.bash >/dev/null 2>&1 # 废弃旧版参数 - + echo "ホスト承認インターセプトを構成しています..." openclaw_permission_update_exec_approvals "allowlist" "on-miss" "deny" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ 標準の安全モードに切り替えられました (すべての危険なコマンドは UI/TG を通じて承認を求めます)${gl_bai}" } @@ -14582,17 +14582,17 @@ except Exception: openclaw_permission_apply_developer() { send_stats "OpenClaw 権限 - 開発拡張モード" openclaw_permission_require_openclaw || return 1 - + echo "アプリケーション層ポリシーを構成しています..." openclaw config set tools.profile coding >/dev/null 2>&1 openclaw config set tools.exec.security allowlist >/dev/null 2>&1 openclaw config set tools.exec.ask on-miss >/dev/null 2>&1 openclaw config set tools.elevated.enabled true >/dev/null 2>&1 # 允许智能体申请提权 openclaw config set tools.exec.strictInlineEval false >/dev/null 2>&1 - + echo "ホスト承認インターセプトを構成しています..." openclaw_permission_update_exec_approvals "allowlist" "on-miss" "deny" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ 開発拡張モードに切り替えました (権限昇格は許可されていますが、一般的な危険なコマンドには引き続き承認が必要です)${gl_bai}" } @@ -14600,33 +14600,33 @@ except Exception: openclaw_permission_apply_full() { send_stats "OpenClaw 権限 - 完全オープン モード" openclaw_permission_require_openclaw || return 1 - + echo "アプリケーション層ポリシーを構成しています..." openclaw config set tools.profile full >/dev/null 2>&1 openclaw config set tools.exec.security full >/dev/null 2>&1 openclaw config set tools.exec.ask off >/dev/null 2>&1 openclaw config set tools.elevated.enabled true >/dev/null 2>&1 openclaw config set tools.exec.strictInlineEval false >/dev/null 2>&1 - + echo "ホストの迎撃防御が崩壊中..." # ここでの full と off は、基礎となるホストの実行承認システムを完全にバイパスします。 openclaw_permission_update_exec_approvals "full" "off" "full" - + openclaw_permission_restart_gateway - echo -e "${gl_lv}✅ 完全オープン モードに切り替えられました (警告: すべてのホスト コマンド インターセプトの有効期限が切れており、エージェントには最高の権限が与えられています)${gl_bai}" + echo -e "${gl_lv}✅ 完全オープン モードに切り替えられています (警告: すべてのホスト コマンドのインターセプトの有効期限が切れており、エージェントには最高の権限が与えられています)${gl_bai}" } openclaw_permission_restore_official_defaults() { send_stats "OpenClaw 権限 - 公式のデフォルトに戻す" openclaw_permission_require_openclaw || return 1 - + echo "クリーンなアプリケーション層の適用範囲を強化します..." openclaw config unset tools.profile >/dev/null 2>&1 openclaw config unset tools.exec.security >/dev/null 2>&1 openclaw config unset tools.exec.ask >/dev/null 2>&1 openclaw config unset tools.elevated.enabled >/dev/null 2>&1 openclaw config unset tools.exec.strictInlineEval >/dev/null 2>&1 - + echo "クリーンなホストインターセプト構成..." # CLI を介して承認設定をクリアすることを優先し、ファイルの直接削除に戻ります。 if echo '{"version":1,"defaults":{}}' | openclaw approvals set --stdin >/dev/null 2>&1; then @@ -14634,7 +14634,7 @@ except Exception: else rm -f "$HOME/.openclaw/exec-approvals.json" fi - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ OpenClaw 公式セキュリティ サンドボックス防御メカニズムに戻しました${gl_bai}" } @@ -15443,7 +15443,7 @@ openclaw_backup_restore_menu() { 8) install_plugin ;; 9) install_skill ;; 10) nano_openclaw_json ;; - 11) send_stats "初期設定ウィザード" + 11) send_stats "初期構成ウィザード" openclaw onboard --install-daemon break_end ;; @@ -15513,7 +15513,7 @@ while true; do echo -e "${gl_kjlan}1. ${color1}パゴダパネル正式版${gl_kjlan}2. ${color2}aaPanel パゴダ国際版" echo -e "${gl_kjlan}3. ${color3}1Panel 新世代管理パネル${gl_kjlan}4. ${color4}NginxProxyManager 視覚化パネル" - echo -e "${gl_kjlan}5. ${color5}OpenList マルチストア ファイル リスト プログラム${gl_kjlan}6. ${color6}Ubuntu リモート デスクトップ Web バージョン" + echo -e "${gl_kjlan}5. ${color5}OpenList マルチストア ファイル リスト プログラム${gl_kjlan}6. ${color6}Ubuntu リモート デスクトップ Web エディション" echo -e "${gl_kjlan}7. ${color7}Nezha Probe VPS 監視パネル${gl_kjlan}8. ${color8}QBオフラインBT磁気ダウンロードパネル" echo -e "${gl_kjlan}9. ${color9}Poste.io メール サーバー プログラム${gl_kjlan}10. ${color10}RocketChat 複数人オンライン チャット システム" echo -e "${gl_kjlan}-------------------------" @@ -15579,6 +15579,7 @@ while true; do echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}111. ${color111}マルチフォーマットファイル変換ツール${gl_kjlan}112. ${color112}Lucky 大規模イントラネット侵入ツール" echo -e "${gl_kjlan}113. ${color113}Firefoxブラウザ${gl_kjlan}114. ${color114}OpenClaw ボット管理ツール${gl_huang}★${gl_bai}" + echo -e "${gl_kjlan}115. ${color115}ヘルメスロボット管理ツール${gl_huang}★${gl_bai}" echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}サードパーティ製アプリケーションのリスト" echo -e "${gl_kjlan}あなたのアプリをここに表示したいですか?開発者ガイドを確認してください。${gl_huang}https://dev.kejilion.sh/${gl_bai}" @@ -15803,7 +15804,7 @@ while true; do check_docker_app check_docker_image_update $docker_name clear - echo -e "ネザ監視$check_docker $update_status" + echo -e "ネザモニタリング$check_docker $update_status" echo "オープンソースの軽量で使いやすいサーバー監視および運用保守ツール" echo "公式 Web サイト構築ドキュメント: https://nezha.wiki/guide/dashboard.html" if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "$docker_name"; then @@ -15812,7 +15813,7 @@ while true; do fi echo "" echo "------------------------" - echo "1. 使用する" + echo "1. 使用方法" echo "------------------------" echo "0. 前のメニューに戻る" echo "------------------------" @@ -17897,7 +17898,7 @@ while true; do local app_id="80" local app_name="リンクワーデンのブックマーク管理" - local app_text="タグ付け、検索、チーム コラボレーションをサポートするオープンソースの自己ホスト型ブックマーク管理プラットフォーム。" + local app_text="タグ付け、検索、チーム コラボレーションをサポートする、オープン ソースの自己ホスト型ブックマーク管理プラットフォーム。" local app_url="公式サイト:https://linkwarden.app/" local docker_name="linkwarden-linkwarden-1" local docker_port="8080" @@ -18206,7 +18207,7 @@ while true; do } - local docker_describe="リモートで映画や生放送を一緒に視聴するプログラム。同時視聴、ライブブロードキャスト、チャットなどの機能を提供します" + local docker_describe="リモートで映画や生放送を一緒に見るプログラム。同時視聴、ライブブロードキャスト、チャットなどの機能を提供します" local docker_url="公式サイト紹介:${gh_https_url}github.com/synctv-org/synctv" local docker_use="echo \"初期アカウントとパスワード: root。ログイン後、時間内にログイン パスワードを変更してください\"" local docker_passwd="" @@ -18236,7 +18237,7 @@ while true; do } - local docker_describe="オープンソースの無料の自作ライブ ブロードキャスト プラットフォーム" + local docker_describe="オープンソース、無料の自社構築ライブ ブロードキャスト プラットフォーム" local docker_url="公式サイト紹介:https://owncast.online" local docker_use="echo \"管理者ページにアクセスするには、アクセス アドレスの後に /admin を続けます\"" local docker_passwd="echo \"初期アカウント: admin 初期パスワード: abc123 ログイン後、時間内にログイン パスワードを変更してください\"" @@ -19246,6 +19247,9 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ moltbot_menu ;; + 115|hermes) + bash <(curl -sL ${gh_proxy}raw.githubusercontent.com/kejilion/sh/main/hermes_manager.sh) + ;; b) clear @@ -19287,7 +19291,7 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ r) root_use send_stats "すべてのアプリを復元する" - echo "利用可能なアプリケーションのバックアップ" + echo "利用可能なアプリのバックアップ" echo "-------------------------" ls -lt /app*.gz | awk '{print $NF}' echo "" @@ -20780,7 +20784,7 @@ EOF echo -e "${gl_lv}現在設定されている受信トラフィック制限のしきい値は次のとおりです。${gl_huang}${rx_threshold_gb}${gl_lv}G${gl_bai}" echo -e "${gl_lv}現在設定されている送信トラフィック制限のしきい値は次のとおりです。${gl_huang}${tx_threshold_gb}${gl_lv}GB${gl_bai}" else - echo -e "${gl_hui}電流制限シャットダウン機能は現在有効になっていません。${gl_bai}" + echo -e "${gl_hui}電流制限シャットダウン機能は現在有効になっていません${gl_bai}" fi echo @@ -21284,7 +21288,7 @@ linux_file() { continue fi - read -e -p "宛先パス (新しいファイル名またはディレクトリ名を含む) を入力してください:" dest_path + read -e -p "宛先パス (新しいファイルまたはディレクトリ名を含む) を入力してください:" dest_path if [ -z "$dest_path" ]; then echo "エラー: 宛先パスを入力してください。" send_stats "ファイルまたはディレクトリの移動に失敗しました: 宛先パスが指定されていません" @@ -21304,7 +21308,7 @@ linux_file() { continue fi - read -e -p "宛先パス (新しいファイル名またはディレクトリ名を含む) を入力してください:" dest_path + read -e -p "宛先パス (新しいファイルまたはディレクトリ名を含む) を入力してください:" dest_path if [ -z "$dest_path" ]; then echo "エラー: 宛先パスを入力してください。" send_stats "ファイルまたはディレクトリのコピーに失敗しました: 宛先パスが指定されていません" @@ -21398,7 +21402,7 @@ run_commands_on_servers() { local username=${SERVER_ARRAY[i+3]} local password=${SERVER_ARRAY[i+4]} echo - echo -e "${gl_huang}に接続します$name ($hostname)...${gl_bai}" + echo -e "${gl_huang}に接続する$name ($hostname)...${gl_bai}" # sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$hostname" -p "$port" "$1" sshpass -p "$password" ssh -t -o StrictHostKeyChecking=no "$username@$hostname" -p "$port" "$1" done @@ -21427,7 +21431,7 @@ while true; do echo -e "${gl_kjlan}------------------------${gl_bai}" echo -e "${gl_kjlan}サーバーリスト管理${gl_bai}" echo -e "${gl_kjlan}1. ${gl_bai}サーバーの追加${gl_kjlan}2. ${gl_bai}サーバーの削除${gl_kjlan}3. ${gl_bai}サーバーの編集" - echo -e "${gl_kjlan}4. ${gl_bai}バックアップクラスター${gl_kjlan}5. ${gl_bai}クラスターを復元する" + echo -e "${gl_kjlan}4. ${gl_bai}バックアップクラスタ${gl_kjlan}5. ${gl_bai}クラスターを復元する" echo -e "${gl_kjlan}------------------------${gl_bai}" echo -e "${gl_kjlan}タスクをバッチで実行する${gl_bai}" echo -e "${gl_kjlan}11. ${gl_bai}テクノロジ ライオン スクリプトをインストールする${gl_kjlan}12. ${gl_bai}アップデートシステム${gl_kjlan}13. ${gl_bai}システムをクリーンアップする" @@ -21465,7 +21469,7 @@ while true; do 4) clear - send_stats "バックアップクラスター" + send_stats "バックアップクラスタ" echo -e "変更してください${gl_huang}/root/cluster/servers.py${gl_bai}ファイルをダウンロードしてバックアップを完了してください。" break_end ;; @@ -21830,13 +21834,13 @@ done k_info() { -send_stats "k コマンドのリファレンス例" +send_stats "k コマンドリファレンスの使用例" echo "-------------------" echo "ビデオ紹介: https://www.bilibili.com/video/BV1ib421E7it?t=0.1" echo "以下は、k コマンドの参考使用例です。" echo "スクリプトkを開始します" echo "パッケージをインストールします k install nano wget | k ナノ wget を追加 | nano wgetをインストールします" -echo "パッケージをアンインストールします。 k 削除 nano wget | kデルナノwget | k nano wget をアンインストールする | nano wgetをアンインストールします" +echo "パッケージをアンインストールします。 k 削除 nano wget | kデルナノwget | nano wget をアンインストールする | nano wgetをアンインストールします" echo "システム k アップデートを更新 | kアップデート" echo "クリーン系ジャンククリーン |きれいだ" echo "システムパネルを再度取り付けます。 k再インストール" diff --git a/kejilion.sh b/kejilion.sh index 57493096e..3245a7fc1 100644 --- a/kejilion.sh +++ b/kejilion.sh @@ -458,6 +458,27 @@ install_add_docker_cn install_add_docker() { echo -e "${gl_kjlan}正在安装docker环境...${gl_bai}" + + # 选择 Docker 数据目录 + echo -e "${gl_kjlan}------------------------" + echo -e "${gl_kjlan}1. ${gl_bai}安装Docker到系统默认路径 (/home/docker)" + echo -e "${gl_kjlan}2. ${gl_bai}安装Docker到其他数据盘" + echo -e "${gl_kjlan}------------------------${gl_bai}" + read -e -p "请输入你的选择 (默认1): " docker_dir_choice + docker_dir_choice=${docker_dir_choice:-1} + + local DOCKER_DIR="/home/docker" + if [ "$docker_dir_choice" = "2" ]; then + read -e -p "请输入Docker数据目录路径 (例如 /mnt/sdb/docker): " custom_docker_dir + if [ -n "$custom_docker_dir" ]; then + DOCKER_DIR="$custom_docker_dir" + fi + fi + + # 保存配置 + set_docker_dir "$DOCKER_DIR" + mkdir -p "$DOCKER_DIR" + if command -v apt &>/dev/null || command -v yum &>/dev/null || command -v dnf &>/dev/null; then linuxmirrors_install_docker else @@ -465,6 +486,12 @@ install_add_docker() { install_add_docker_cn fi + + # 如果选择了数据盘,配置 Docker data-root + if [ "$DOCKER_DIR" != "/home/docker" ]; then + configure_docker_data_root "$DOCKER_DIR" + fi + sleep 2 } @@ -2826,34 +2853,183 @@ clear_host_port_rules() { } +# 获取 Docker 数据目录配置 +get_docker_dir() { + if [ -f "/etc/docker/kejilion_docker_dir.conf" ]; then + cat /etc/docker/kejilion_docker_dir.conf + else + echo "/home/docker" + fi +} + +# 设置 Docker 数据目录 +set_docker_dir() { + local docker_dir="$1" + mkdir -p /etc/docker + echo "$docker_dir" > /etc/docker/kejilion_docker_dir.conf +} + +# 配置 Docker data-root +configure_docker_data_root() { + local docker_dir="$1" + install jq + + local CONFIG_FILE="/etc/docker/daemon.json" + local DATA_ROOT="$docker_dir/docker-data" + + mkdir -p "$DATA_ROOT" + + if [ ! -f "$CONFIG_FILE" ]; then + echo "{\"data-root\": \"$DATA_ROOT\"}" | jq . > "$CONFIG_FILE" + else + local ORIGINAL_CONFIG=$(<"$CONFIG_FILE") + local UPDATED_CONFIG=$(echo "$ORIGINAL_CONFIG" | jq --arg dr "$DATA_ROOT" '. + {"data-root": $dr}') + echo "$UPDATED_CONFIG" | jq . > "$CONFIG_FILE" + fi + + restart docker + echo -e "${gl_lv}Docker数据目录已设置为: $DATA_ROOT${gl_bai}" + echo -e "${gl_lv}Docker应用数据目录已设置为: $docker_dir${gl_bai}" +} + +# 显示应用安装信息(数据目录、compose文件路径、挂载卷) +show_app_info() { + local app_name="$1" + local DOCKER_DIR=$(get_docker_dir) + + echo "------------------------" + echo -e "${gl_kjlan}应用信息:${gl_bai}" + echo -e " 数据目录: ${gl_lv}$DOCKER_DIR/$app_name${gl_bai}" + + # 检查是否为 docker-compose 安装 + if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "$app_name"; then + local compose_project=$(docker inspect "$app_name" 2>/dev/null | jq -r '.[0].Config.Labels["com.docker.compose.project.working_dir"] // empty' 2>/dev/null) + if [ -n "$compose_project" ]; then + echo -e " docker-compose文件: ${gl_lv}$compose_project/docker-compose.yml${gl_bai}" + fi + fi + + # 列出所有挂载卷 + if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "$app_name"; then + local volumes=$(docker inspect "$app_name" 2>/dev/null | jq -r '.[0].Mounts[] | "\(.Source) -> \(.Destination)"' 2>/dev/null) + if [ -n "$volumes" ]; then + echo -e " 挂载目录:" + echo "$volumes" | while read -r line; do + echo -e " ${gl_lv}$line${gl_bai}" + done + fi + fi + echo "------------------------" +} + +# 迁移 Docker 数据目录 +migrate_docker_dir() { + local CURRENT_DIR=$(get_docker_dir) + echo -e "${gl_kjlan}迁移Docker数据目录${gl_bai}" + echo -e "当前Docker应用数据目录: ${gl_lv}$CURRENT_DIR${gl_bai}" + + # 显示当前 Docker data-root + if command -v docker &>/dev/null; then + local CURRENT_DATA_ROOT=$(docker info 2>/dev/null | grep "Docker Root Dir" | awk '{print $NF}') + echo -e "当前Docker系统数据目录: ${gl_lv}$CURRENT_DATA_ROOT${gl_bai}" + fi + + echo "" + echo -e "${gl_kjlan}------------------------" + echo -e "${gl_kjlan}1. ${gl_bai}迁移到其他数据盘" + echo -e "${gl_kjlan}0. ${gl_bai}返回" + echo -e "${gl_kjlan}------------------------${gl_bai}" + read -e -p "请输入你的选择: " mig_choice + + if [ "$mig_choice" = "1" ]; then + read -e -p "请输入目标数据目录路径 (例如 /mnt/sdb/docker): " target_dir + if [ -z "$target_dir" ]; then + echo "未输入目标路径,取消迁移" + return + fi + + if [ "$target_dir" = "$CURRENT_DIR" ]; then + echo -e "${gl_huang}目标路径与当前路径相同,无需迁移${gl_bai}" + return + fi + + # 检查 rsync + install rsync + + echo -e "${gl_huang}即将执行迁移操作,请确保已停止所有运行中的Docker容器${gl_bai}" + read -e -p "是否停止所有Docker容器并继续迁移?(Y/N): " confirm + if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + echo "取消迁移" + return + fi + + # 停止所有容器 + docker ps -q | xargs -r docker stop + + # 迁移应用数据 + echo "正在迁移应用数据 $CURRENT_DIR -> $target_dir ..." + mkdir -p "$target_dir" + rsync -avHAXS --progress "$CURRENT_DIR/" "$target_dir/" + + # 迁移 Docker 系统数据 + local CURRENT_DATA_ROOT=$(docker info 2>/dev/null | grep "Docker Root Dir" | awk '{print $NF}') + local TARGET_DATA_ROOT="$target_dir/docker-data" + + if [ -n "$CURRENT_DATA_ROOT" ] && [ "$CURRENT_DATA_ROOT" != "$TARGET_DATA_ROOT" ]; then + echo "正在迁移Docker系统数据 $CURRENT_DATA_ROOT -> $TARGET_DATA_ROOT ..." + mkdir -p "$TARGET_DATA_ROOT" + rsync -avHAXS --progress "$CURRENT_DATA_ROOT/" "$TARGET_DATA_ROOT/" + + # 更新 daemon.json + configure_docker_data_root "$target_dir" + fi + + # 更新配置 + set_docker_dir "$target_dir" + + # 启动 Docker + start docker + + echo -e "${gl_lv}迁移完成!${gl_bai}" + echo -e "新的应用数据目录: ${gl_lv}$target_dir${gl_bai}" + echo -e "新的Docker系统数据目录: ${gl_lv}$TARGET_DATA_ROOT${gl_bai}" + echo -e "${gl_huang}提示: 确认一切正常后,可手动删除旧目录: $CURRENT_DIR 和 $CURRENT_DATA_ROOT${gl_bai}" + fi +} + + setup_docker_dir() { - mkdir -p /home /home/docker 2>/dev/null + local DOCKER_DIR=$(get_docker_dir) + mkdir -p "$DOCKER_DIR" 2>/dev/null - if [ -d "/vol1/1000/" ] && [ ! -d "/vol1/1000/docker" ]; then - cp -f /home/docker /home/docker1 2>/dev/null - rm -rf /home/docker 2>/dev/null - mkdir -p /vol1/1000/docker 2>/dev/null - ln -s /vol1/1000/docker /home/docker 2>/dev/null - fi + # 群晖兼容逻辑仅在默认路径时生效 + if [ "$DOCKER_DIR" = "/home/docker" ]; then + if [ -d "/vol1/1000/" ] && [ ! -d "/vol1/1000/docker" ]; then + cp -f /home/docker /home/docker1 2>/dev/null + rm -rf /home/docker 2>/dev/null + mkdir -p /vol1/1000/docker 2>/dev/null + ln -s /vol1/1000/docker /home/docker 2>/dev/null + fi - if [ -d "/volume1/" ] && [ ! -d "/volume1/docker" ]; then - cp -f /home/docker /home/docker1 2>/dev/null - rm -rf /home/docker 2>/dev/null - mkdir -p /volume1/docker 2>/dev/null - ln -s /volume1/docker /home/docker 2>/dev/null + if [ -d "/volume1/" ] && [ ! -d "/volume1/docker" ]; then + cp -f /home/docker /home/docker1 2>/dev/null + rm -rf /home/docker 2>/dev/null + mkdir -p /volume1/docker 2>/dev/null + ln -s /volume1/docker /home/docker 2>/dev/null + fi fi - } add_app_id() { -mkdir -p /home/docker -touch /home/docker/appno.txt -grep -qxF "${app_id}" /home/docker/appno.txt || echo "${app_id}" >> /home/docker/appno.txt +local DOCKER_DIR=$(get_docker_dir) +mkdir -p "$DOCKER_DIR" +touch "$DOCKER_DIR/appno.txt" +grep -qxF "${app_id}" "$DOCKER_DIR/appno.txt" || echo "${app_id}" >> "$DOCKER_DIR/appno.txt" } @@ -2869,13 +3045,14 @@ while true; do echo -e "$docker_name $check_docker $update_status" echo "$docker_describe" echo "$docker_url" + local DOCKER_DIR=$(get_docker_dir) if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "$docker_name"; then - if [ ! -f "/home/docker/${docker_name}_port.conf" ]; then + if [ ! -f "${DOCKER_DIR}/${docker_name}_port.conf" ]; then local docker_port=$(docker port "$docker_name" | head -n1 | awk -F'[:]' '/->/ {print $NF; exit}') docker_port=${docker_port:-0000} - echo "$docker_port" > "/home/docker/${docker_name}_port.conf" + echo "$docker_port" > "${DOCKER_DIR}/${docker_name}_port.conf" fi - local docker_port=$(cat "/home/docker/${docker_name}_port.conf") + local docker_port=$(cat "${DOCKER_DIR}/${docker_name}_port.conf") check_docker_app_ip fi echo "" @@ -2891,7 +3068,7 @@ while true; do case $choice in 1) setup_docker_dir - check_disk_space $app_size /home/docker + check_disk_space $app_size $(get_docker_dir) while true; do read -e -p "输入应用对外服务端口,回车默认使用${docker_port}端口: " app_port local app_port=${app_port:-${docker_port}} @@ -2908,7 +3085,7 @@ while true; do install jq install_docker docker_rum - echo "$docker_port" > "/home/docker/${docker_name}_port.conf" + echo "$docker_port" > "${DOCKER_DIR}/${docker_name}_port.conf" add_app_id @@ -2918,6 +3095,7 @@ while true; do echo "" $docker_use $docker_passwd + show_app_info "$docker_name" send_stats "安装$docker_name" ;; 2) @@ -2938,10 +3116,11 @@ while true; do 3) docker rm -f "$docker_name" docker rmi -f "$docker_img" - rm -rf "/home/docker/$docker_name" - rm -f /home/docker/${docker_name}_port.conf + local DOCKER_DIR=$(get_docker_dir) + rm -rf "${DOCKER_DIR}/$docker_name" + rm -f "${DOCKER_DIR}/${docker_name}_port.conf" - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" "${DOCKER_DIR}/appno.txt" echo "应用已卸载" send_stats "卸载$docker_name" ;; @@ -2991,13 +3170,14 @@ docker_app_plus() { echo -e "$app_name $check_docker $update_status" echo "$app_text" echo "$app_url" + local DOCKER_DIR=$(get_docker_dir) if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "$docker_name"; then - if [ ! -f "/home/docker/${docker_name}_port.conf" ]; then + if [ ! -f "${DOCKER_DIR}/${docker_name}_port.conf" ]; then local docker_port=$(docker port "$docker_name" | head -n1 | awk -F'[:]' '/->/ {print $NF; exit}') docker_port=${docker_port:-0000} - echo "$docker_port" > "/home/docker/${docker_name}_port.conf" + echo "$docker_port" > "${DOCKER_DIR}/${docker_name}_port.conf" fi - local docker_port=$(cat "/home/docker/${docker_name}_port.conf") + local docker_port=$(cat "${DOCKER_DIR}/${docker_name}_port.conf") check_docker_app_ip fi echo "" @@ -3013,7 +3193,7 @@ docker_app_plus() { case $choice in 1) setup_docker_dir - check_disk_space $app_size /home/docker + check_disk_space $app_size $(get_docker_dir) while true; do read -e -p "输入应用对外服务端口,回车默认使用${docker_port}端口: " app_port @@ -3031,7 +3211,7 @@ docker_app_plus() { install jq install_docker docker_app_install - echo "$docker_port" > "/home/docker/${docker_name}_port.conf" + echo "$docker_port" > "${DOCKER_DIR}/${docker_name}_port.conf" add_app_id send_stats "$app_name 安装" @@ -3045,9 +3225,10 @@ docker_app_plus() { 3) docker_app_uninstall - rm -f /home/docker/${docker_name}_port.conf + local DOCKER_DIR=$(get_docker_dir) + rm -f "${DOCKER_DIR}/${docker_name}_port.conf" - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" "${DOCKER_DIR}/appno.txt" send_stats "$app_name 卸载" ;; @@ -3085,8 +3266,8 @@ docker_app_plus() { prometheus_install() { -local PROMETHEUS_DIR="/home/docker/monitoring/prometheus" -local GRAFANA_DIR="/home/docker/monitoring/grafana" +local PROMETHEUS_DIR="$(get_docker_dir)/monitoring/prometheus" +local GRAFANA_DIR="$(get_docker_dir)/monitoring/grafana" local NETWORK_NAME="monitoring" # Create necessary directories @@ -3684,7 +3865,7 @@ stream_panel() { read -e -p "确定要删除 nginx 容器吗?这可能会影响网站功能!(y/N): " confirm if [[ "$confirm" =~ ^[Yy]$ ]]; then docker rm -f nginx - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" $(get_docker_dir)/appno.txt send_stats "更新Stream四层代理" echo "nginx 容器已删除。" else @@ -4039,7 +4220,7 @@ while true; do 3) panel_app_uninstall - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" $(get_docker_dir)/appno.txt send_stats "${panelname}卸载" ;; *) @@ -4391,7 +4572,7 @@ frps_panel() { close_port 8055 8056 - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" $(get_docker_dir)/appno.txt echo "应用已卸载" ;; 5) @@ -4488,7 +4669,7 @@ frpc_panel() { rm -rf /home/frp close_port 8055 - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" $(get_docker_dir)/appno.txt echo "应用已卸载" ;; @@ -4576,7 +4757,7 @@ yt_menu_pro() { echo "正在卸载 yt-dlp..." rm -f /usr/local/bin/yt-dlp - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" $(get_docker_dir)/appno.txt echo "卸载完成。按任意键继续..." read ;; 5) @@ -5862,19 +6043,19 @@ clamav_scan() { SCAN_PARAMS+="/mnt/host${dir} " done - mkdir -p /home/docker/clamav/log/ > /dev/null 2>&1 - > /home/docker/clamav/log/scan.log > /dev/null 2>&1 + mkdir -p $(get_docker_dir)/clamav/log/ > /dev/null 2>&1 + > $(get_docker_dir)/clamav/log/scan.log > /dev/null 2>&1 # 执行 Docker 命令 docker run --rm \ --name clamav \ --mount source=clam_db,target=/var/lib/clamav \ $MOUNT_PARAMS \ - -v /home/docker/clamav/log/:/var/log/clamav/ \ + -v $(get_docker_dir)/clamav/log/:/var/log/clamav/ \ clamav/clamav-debian:latest \ clamscan -r --log=/var/log/clamav/scan.log $SCAN_PARAMS - echo -e "${gl_lv}$@ 扫描完成,病毒报告存放在${gl_huang}/home/docker/clamav/log/scan.log${gl_bai}" + echo -e "${gl_lv}$@ 扫描完成,病毒报告存放在${gl_huang}$(get_docker_dir)/clamav/log/scan.log${gl_bai}" echo -e "${gl_lv}如果有病毒请在${gl_huang}scan.log${gl_lv}文件中搜索FOUND关键字确认病毒位置 ${gl_bai}" } @@ -8093,11 +8274,11 @@ docker_ssh_migration() { done - # 备份 /home/docker 下的所有文件(不含子目录) - if [ -d "/home/docker" ]; then - echo -e "${gl_kjlan}备份 /home/docker 下的文件...${gl_bai}" - find /home/docker -maxdepth 1 -type f | tar -czf "${BACKUP_DIR}/home_docker_files.tar.gz" -T - - echo -e "${gl_lv}/home/docker 下的文件已打包到: ${BACKUP_DIR}/home_docker_files.tar.gz${gl_bai}" + # 备份 $(get_docker_dir) 下的所有文件(不含子目录) + if [ -d "$(get_docker_dir)" ]; then + echo -e "${gl_kjlan}备份 $(get_docker_dir) 下的文件...${gl_bai}" + find $(get_docker_dir) -maxdepth 1 -type f | tar -czf "${BACKUP_DIR}/home_docker_files.tar.gz" -T - + echo -e "${gl_lv}$(get_docker_dir) 下的文件已打包到: ${BACKUP_DIR}/home_docker_files.tar.gz${gl_bai}" fi chmod +x "$RESTORE_SCRIPT" @@ -8212,14 +8393,14 @@ docker_ssh_migration() { [[ "$has_container" == false ]] && echo -e "${gl_huang}未找到普通容器的备份信息${gl_bai}" - # 还原 /home/docker 下的文件 + # 还原 $(get_docker_dir) 下的文件 if [ -f "$BACKUP_DIR/home_docker_files.tar.gz" ]; then - echo -e "${gl_kjlan}正在还原 /home/docker 下的文件...${gl_bai}" - mkdir -p /home/docker + echo -e "${gl_kjlan}正在还原 $(get_docker_dir) 下的文件...${gl_bai}" + mkdir -p $(get_docker_dir) tar -xzf "$BACKUP_DIR/home_docker_files.tar.gz" -C / - echo -e "${gl_lv}/home/docker 下的文件已还原完成${gl_bai}" + echo -e "${gl_lv}$(get_docker_dir) 下的文件已还原完成${gl_bai}" else - echo -e "${gl_huang}未找到 /home/docker 下文件的备份,跳过...${gl_bai}" + echo -e "${gl_huang}未找到 $(get_docker_dir) 下文件的备份,跳过...${gl_bai}" fi @@ -8325,6 +8506,7 @@ linux_docker() { echo -e "${gl_kjlan}------------------------" echo -e "${gl_kjlan}11. ${gl_bai}开启Docker-ipv6访问" echo -e "${gl_kjlan}12. ${gl_bai}关闭Docker-ipv6访问" + echo -e "${gl_kjlan}13. ${gl_bai}迁移Docker数据目录 ${gl_huang}★${gl_bai}" echo -e "${gl_kjlan}------------------------" echo -e "${gl_kjlan}19. ${gl_bai}备份/迁移/还原Docker环境" echo -e "${gl_kjlan}20. ${gl_bai}卸载Docker环境" @@ -8549,6 +8731,12 @@ linux_docker() { docker_ipv6_off ;; + 13) + clear + send_stats "迁移Docker数据目录" + migrate_docker_dir + ;; + 19) docker_ssh_migration ;; @@ -15277,7 +15465,7 @@ openclaw_backup_restore_menu() { rm -rf "$HOME/.openclaw" [ "$HOME" != "/root" ] && [ -d /root/.openclaw ] && echo "⚠️ 检测到 root 目录下仍存在 /root/.openclaw,如需清理请手动处理" hash -r - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" $(get_docker_dir)/appno.txt echo "卸载完成" break_end } @@ -15500,7 +15688,7 @@ while true; do echo -e "应用市场" echo -e "${gl_kjlan}-------------------------" - local app_numbers=$([ -f /home/docker/appno.txt ] && cat /home/docker/appno.txt || echo "") + local app_numbers=$([ -f $(get_docker_dir)/appno.txt ] && cat $(get_docker_dir)/appno.txt || echo "") # 用循环设置颜色 for i in {1..150}; do @@ -15700,8 +15888,8 @@ while true; do -p ${docker_port}:81 \ -p 80:80 \ -p 443:443 \ - -v /home/docker/npm/data:/data \ - -v /home/docker/npm/letsencrypt:/etc/letsencrypt \ + -v $(get_docker_dir)/npm/data:/data \ + -v $(get_docker_dir)/npm/letsencrypt:/etc/letsencrypt \ --restart=always \ $docker_img @@ -15727,12 +15915,12 @@ while true; do docker_rum() { - mkdir -p /home/docker/openlist - chmod -R 777 /home/docker/openlist + mkdir -p $(get_docker_dir)/openlist + chmod -R 777 $(get_docker_dir)/openlist docker run -d \ --restart=always \ - -v /home/docker/openlist:/opt/openlist/data \ + -v $(get_docker_dir)/openlist:/opt/openlist/data \ -p ${docker_port}:5244 \ -e PUID=0 \ -e PGID=0 \ @@ -15774,7 +15962,7 @@ while true; do -e CUSTOM_USER=${admin} \ -e PASSWORD=${admin_password} \ -p ${docker_port}:3000 \ - -v /home/docker/webtop/data:/config \ + -v $(get_docker_dir)/webtop/data:/config \ -v /var/run/docker.sock:/var/run/docker.sock \ --shm-size="1gb" \ --restart=always \ @@ -15857,8 +16045,8 @@ while true; do -p ${docker_port}:${docker_port} \ -p 56881:56881 \ -p 56881:56881/udp \ - -v /home/docker/qbittorrent/config:/config \ - -v /home/docker/qbittorrent/downloads:/downloads \ + -v $(get_docker_dir)/qbittorrent/config:/config \ + -v $(get_docker_dir)/qbittorrent/downloads:/downloads \ --restart=always \ lscr.io/linuxserver/qbittorrent:latest @@ -15900,7 +16088,7 @@ while true; do echo "" if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "$docker_name"; then - yuming=$(cat /home/docker/mail.txt) + yuming=$(cat $(get_docker_dir)/mail.txt) echo "访问地址: " echo "https://$yuming" fi @@ -15915,10 +16103,10 @@ while true; do case $choice in 1) setup_docker_dir - check_disk_space 2 /home/docker + check_disk_space 2 $(get_docker_dir) read -e -p "请设置邮箱域名 例如 mail.yuming.com : " yuming - mkdir -p /home/docker - echo "$yuming" > /home/docker/mail.txt + mkdir -p $(get_docker_dir) + echo "$yuming" > $(get_docker_dir)/mail.txt echo "------------------------" ip_address echo "先解析这些DNS记录" @@ -15940,7 +16128,7 @@ while true; do docker run \ --net=host \ -e TZ=Europe/Prague \ - -v /home/docker/mail:/data \ + -v $(get_docker_dir)/mail:/data \ --name "mailserver" \ -h "$yuming" \ --restart=always \ @@ -15951,6 +16139,7 @@ while true; do clear echo "poste.io已经安装完成" + show_app_info "$docker_name" echo "------------------------" echo "您可以使用以下地址访问poste.io:" echo "https://$yuming" @@ -15961,11 +16150,11 @@ while true; do 2) docker rm -f mailserver docker rmi -f analogic/poste.i - yuming=$(cat /home/docker/mail.txt) + yuming=$(cat $(get_docker_dir)/mail.txt) docker run \ --net=host \ -e TZ=Europe/Prague \ - -v /home/docker/mail:/data \ + -v $(get_docker_dir)/mail:/data \ --name "mailserver" \ -h "$yuming" \ --restart=always \ @@ -15976,6 +16165,7 @@ while true; do clear echo "poste.io已经安装完成" + show_app_info "$docker_name" echo "------------------------" echo "您可以使用以下地址访问poste.io:" echo "https://$yuming" @@ -15984,10 +16174,10 @@ while true; do 3) docker rm -f mailserver docker rmi -f analogic/poste.io - rm /home/docker/mail.txt - rm -rf /home/docker/mail + rm $(get_docker_dir)/mail.txt + rm -rf $(get_docker_dir)/mail - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" $(get_docker_dir)/appno.txt echo "应用已卸载" ;; @@ -16013,7 +16203,7 @@ while true; do docker_app_install() { docker run --name db -d --restart=always \ - -v /home/docker/mongo/dump:/dump \ + -v $(get_docker_dir)/mongo/dump:/dump \ mongo:latest --replSet rs5 --oplogSize 256 sleep 1 docker exec db mongosh --eval "printjson(rs.initiate())" @@ -16023,6 +16213,7 @@ while true; do clear ip_address echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } @@ -16033,6 +16224,7 @@ while true; do clear ip_address echo "rocket.chat已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } @@ -16041,7 +16233,7 @@ while true; do docker rmi -f rocket.chat docker rm -f db docker rmi -f mongo:latest - rm -rf /home/docker/mongo + rm -rf $(get_docker_dir)/mongo echo "应用已卸载" } @@ -16063,7 +16255,7 @@ while true; do docker run -d -p ${docker_port}:80 \ -e ADMINER_USER="root" -e ADMINER_PASSWD="password" \ -e BIND_ADDRESS="false" \ - -v /home/docker/zentao-server/:/opt/zbox/ \ + -v $(get_docker_dir)/zentao-server/:/opt/zbox/ \ --add-host smtp.exmail.qq.com:163.177.90.125 \ --name zentao-server \ --restart=always \ @@ -16091,7 +16283,7 @@ while true; do docker run -d \ - -v /home/docker/qinglong/data:/ql/data \ + -v $(get_docker_dir)/qinglong/data:/ql/data \ -p ${docker_port}:5700 \ --name qinglong \ --hostname qinglong \ @@ -16121,25 +16313,26 @@ while true; do docker_app_install() { cd /home/ && mkdir -p docker/cloud && cd docker/cloud && mkdir temp_data && mkdir -vp cloudreve/{uploads,avatar} && touch cloudreve/conf.ini && touch cloudreve/cloudreve.db && mkdir -p aria2/config && mkdir -p data/aria2 && chmod -R 777 data/aria2 - curl -o /home/docker/cloud/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/cloudreve-docker-compose.yml - sed -i "s/5212:5212/${docker_port}:5212/g" /home/docker/cloud/docker-compose.yml - cd /home/docker/cloud/ + curl -o $(get_docker_dir)/cloud/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/cloudreve-docker-compose.yml + sed -i "s/5212:5212/${docker_port}:5212/g" $(get_docker_dir)/cloud/docker-compose.yml + cd $(get_docker_dir)/cloud/ docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/cloud/ && docker compose down --rmi all - cd /home/docker/cloud/ && docker compose up -d + cd $(get_docker_dir)/cloud/ && docker compose down --rmi all + cd $(get_docker_dir)/cloud/ && docker compose up -d } docker_app_uninstall() { - cd /home/docker/cloud/ && docker compose down --rmi all - rm -rf /home/docker/cloud + cd $(get_docker_dir)/cloud/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/cloud echo "应用已卸载" } @@ -16159,8 +16352,8 @@ while true; do -e TZ=Asia/Shanghai \ -e PUID=1000 \ -e PGID=1000 \ - -v /home/docker/easyimage/config:/app/web/config \ - -v /home/docker/easyimage/i:/app/web/i \ + -v $(get_docker_dir)/easyimage/config:/app/web/config \ + -v $(get_docker_dir)/easyimage/i:/app/web/i \ --restart=always \ ddsderek/easyimage:latest @@ -16183,9 +16376,9 @@ while true; do docker_rum() { docker run -d --name=emby --restart=always \ - -v /home/docker/emby/config:/config \ - -v /home/docker/emby/share1:/mnt/share1 \ - -v /home/docker/emby/share2:/mnt/share2 \ + -v $(get_docker_dir)/emby/config:/config \ + -v $(get_docker_dir)/emby/share1:/mnt/share1 \ + -v $(get_docker_dir)/emby/share2:/mnt/share2 \ -v /mnt/notify:/mnt/notify \ -p ${docker_port}:8096 \ -e UID=1000 -e GID=100 -e GIDLIST=100 \ @@ -16234,8 +16427,8 @@ while true; do docker run -d \ --name adguardhome \ - -v /home/docker/adguardhome/work:/opt/adguardhome/work \ - -v /home/docker/adguardhome/conf:/opt/adguardhome/conf \ + -v $(get_docker_dir)/adguardhome/work:/opt/adguardhome/work \ + -v $(get_docker_dir)/adguardhome/conf:/opt/adguardhome/conf \ -p 53:53/tcp \ -p 53:53/udp \ -p ${docker_port}:3000/tcp \ @@ -16268,8 +16461,8 @@ while true; do docker run -d -p ${docker_port}:80 \ --restart=always \ --name onlyoffice \ - -v /home/docker/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \ - -v /home/docker/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data \ + -v $(get_docker_dir)/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \ + -v $(get_docker_dir)/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data \ onlyoffice/documentserver @@ -16317,6 +16510,7 @@ while true; do add_app_id clear echo "雷池WAF面板已经安装完成" + show_app_info "$docker_name" check_docker_app_ip docker exec safeline-mgt resetadmin @@ -16339,7 +16533,7 @@ while true; do cd /data/safeline docker compose down --rmi all - sed -i "/\b${app_id}\b/d" /home/docker/appno.txt + sed -i "/\b${app_id}\b/d" $(get_docker_dir)/appno.txt echo "如果你是默认安装目录那现在项目已经卸载。如果你是自定义安装目录你需要到安装目录下自行执行:" echo "docker compose down && docker compose down --rmi all" ;; @@ -16365,7 +16559,7 @@ while true; do --name portainer \ -p ${docker_port}:9000 \ -v /var/run/docker.sock:/var/run/docker.sock \ - -v /home/docker/portainer:/data \ + -v $(get_docker_dir)/portainer:/data \ --restart=always \ portainer/portainer @@ -16390,7 +16584,7 @@ while true; do docker_rum() { - docker run -d -p ${docker_port}:8080 -v /home/docker/vscode-web:/home/coder/.local/share/code-server --name vscode-web --restart=always codercom/code-server + docker run -d -p ${docker_port}:8080 -v $(get_docker_dir)/vscode-web:/home/coder/.local/share/code-server --name vscode-web --restart=always codercom/code-server } @@ -16416,7 +16610,7 @@ while true; do docker run -d \ --name=uptime-kuma \ -p ${docker_port}:3001 \ - -v /home/docker/uptime-kuma/uptime-kuma-data:/app/data \ + -v $(get_docker_dir)/uptime-kuma/uptime-kuma-data:/app/data \ --restart=always \ louislam/uptime-kuma:latest @@ -16439,7 +16633,7 @@ while true; do docker_rum() { - docker run -d --name memos -p ${docker_port}:5230 -v /home/docker/memos:/var/opt/memos --restart=always neosmemo/memos:stable + docker run -d --name memos -p ${docker_port}:5230 -v $(get_docker_dir)/memos:/var/opt/memos --restart=always neosmemo/memos:stable } @@ -16475,7 +16669,7 @@ while true; do -e DOCKER_MODS=linuxserver/mods:universal-package-install \ -e INSTALL_PACKAGES=font-noto-cjk \ -p ${docker_port}:3000 \ - -v /home/docker/webtop/data:/config \ + -v $(get_docker_dir)/webtop/data:/config \ -v /var/run/docker.sock:/var/run/docker.sock \ --shm-size="1gb" \ --restart=always \ @@ -16501,7 +16695,7 @@ while true; do docker_rum() { - docker run -d --name nextcloud --restart=always -p ${docker_port}:80 -v /home/docker/nextcloud:/var/www/html -e NEXTCLOUD_ADMIN_USER=nextcloud -e NEXTCLOUD_ADMIN_PASSWORD=$rootpasswd nextcloud + docker run -d --name nextcloud --restart=always -p ${docker_port}:80 -v $(get_docker_dir)/nextcloud:/var/www/html -e NEXTCLOUD_ADMIN_USER=nextcloud -e NEXTCLOUD_ADMIN_PASSWORD=$rootpasswd nextcloud } @@ -16521,7 +16715,7 @@ while true; do docker_rum() { - docker run -d --name qd -p ${docker_port}:80 -v /home/docker/qd/config:/usr/src/app/config qdtoday/qd + docker run -d --name qd -p ${docker_port}:80 -v $(get_docker_dir)/qd/config:/usr/src/app/config qdtoday/qd } @@ -16541,7 +16735,7 @@ while true; do docker_rum() { - docker run -d --name dockge --restart=always -p ${docker_port}:5001 -v /var/run/docker.sock:/var/run/docker.sock -v /home/docker/dockge/data:/app/data -v /home/docker/dockge/stacks:/home/docker/dockge/stacks -e DOCKGE_STACKS_DIR=/home/docker/dockge/stacks louislam/dockge + docker run -d --name dockge --restart=always -p ${docker_port}:5001 -v /var/run/docker.sock:/var/run/docker.sock -v $(get_docker_dir)/dockge/data:/app/data -v $(get_docker_dir)/dockge/stacks:$(get_docker_dir)/dockge/stacks -e DOCKGE_STACKS_DIR=$(get_docker_dir)/dockge/stacks louislam/dockge } @@ -16585,7 +16779,7 @@ while true; do --name searxng \ --restart=always \ -p ${docker_port}:8080 \ - -v "/home/docker/searxng:/etc/searxng" \ + -v "$(get_docker_dir)/searxng:/etc/searxng" \ searxng/searxng } @@ -16615,8 +16809,8 @@ while true; do -p ${docker_port}:2342 \ -e PHOTOPRISM_UPLOAD_NSFW="true" \ -e PHOTOPRISM_ADMIN_PASSWORD="$rootpasswd" \ - -v /home/docker/photoprism/storage:/photoprism/storage \ - -v /home/docker/photoprism/Pictures:/photoprism/originals \ + -v $(get_docker_dir)/photoprism/storage:/photoprism/storage \ + -v $(get_docker_dir)/photoprism/Pictures:/photoprism/originals \ photoprism/photoprism } @@ -16643,9 +16837,9 @@ while true; do --name s-pdf \ --restart=always \ -p ${docker_port}:8080 \ - -v /home/docker/s-pdf/trainingData:/usr/share/tesseract-ocr/5/tessdata \ - -v /home/docker/s-pdf/extraConfigs:/configs \ - -v /home/docker/s-pdf/logs:/logs \ + -v $(get_docker_dir)/s-pdf/trainingData:/usr/share/tesseract-ocr/5/tessdata \ + -v $(get_docker_dir)/s-pdf/extraConfigs:/configs \ + -v $(get_docker_dir)/s-pdf/logs:/logs \ -e DOCKER_ENABLE_SECURITY=false \ frooodle/s-pdf:latest } @@ -16666,7 +16860,7 @@ while true; do docker_rum() { - docker run -d --restart=always --name drawio -p ${docker_port}:8080 -v /home/docker/drawio:/var/lib/drawio jgraph/drawio + docker run -d --restart=always --name drawio -p ${docker_port}:8080 -v $(get_docker_dir)/drawio:/var/lib/drawio jgraph/drawio } @@ -16688,9 +16882,9 @@ while true; do docker_rum() { docker run -d --restart=always -p ${docker_port}:3002 \ - -v /home/docker/sun-panel/conf:/app/conf \ - -v /home/docker/sun-panel/uploads:/app/uploads \ - -v /home/docker/sun-panel/database:/app/database \ + -v $(get_docker_dir)/sun-panel/conf:/app/conf \ + -v $(get_docker_dir)/sun-panel/uploads:/app/uploads \ + -v $(get_docker_dir)/sun-panel/database:/app/database \ --name sun-panel \ hslr/sun-panel @@ -16716,7 +16910,7 @@ while true; do --name pingvin-share \ --restart=always \ -p ${docker_port}:3000 \ - -v /home/docker/pingvin-share/data:/opt/app/backend/data \ + -v $(get_docker_dir)/pingvin-share/data:/opt/app/backend/data \ stonith404/pingvin-share } @@ -16739,7 +16933,7 @@ while true; do docker run -d --restart=always \ -p ${docker_port}:3000 \ - -v /home/docker/moments/data:/app/data \ + -v $(get_docker_dir)/moments/data:/app/data \ -v /etc/localtime:/etc/localtime:ro \ -v /etc/timezone:/etc/timezone:ro \ --name moments \ @@ -16810,9 +17004,9 @@ while true; do 39|bililive) - if [ ! -d /home/docker/bililive-go/ ]; then - mkdir -p /home/docker/bililive-go/ > /dev/null 2>&1 - wget -O /home/docker/bililive-go/config.yml ${gh_proxy}raw.githubusercontent.com/hr3lxphr6j/bililive-go/master/config.yml > /dev/null 2>&1 + if [ ! -d $(get_docker_dir)/bililive-go/ ]; then + mkdir -p $(get_docker_dir)/bililive-go/ > /dev/null 2>&1 + wget -O $(get_docker_dir)/bililive-go/config.yml ${gh_proxy}raw.githubusercontent.com/hr3lxphr6j/bililive-go/master/config.yml > /dev/null 2>&1 fi local app_id="39" @@ -16822,7 +17016,7 @@ while true; do docker_rum() { - docker run --restart=always --name bililive-go -v /home/docker/bililive-go/config.yml:/etc/bililive-go/config.yml -v /home/docker/bililive-go/Videos:/srv/bililive -p ${docker_port}:8080 -d chigusa/bililive-go + docker run --restart=always --name bililive-go -v $(get_docker_dir)/bililive-go/config.yml:/etc/bililive-go/config.yml -v $(get_docker_dir)/bililive-go/Videos:/srv/bililive -p ${docker_port}:8080 -d chigusa/bililive-go } @@ -16891,7 +17085,7 @@ while true; do --name nexterm \ -e ENCRYPTION_KEY=${ENCRYPTION_KEY} \ -p ${docker_port}:6989 \ - -v /home/docker/nexterm:/app/data \ + -v $(get_docker_dir)/nexterm:/app/data \ --restart=always \ germannewsmaker/nexterm:latest @@ -16913,7 +17107,7 @@ while true; do docker_rum() { - docker run --name hbbs -v /home/docker/hbbs/data:/root -td --net=host --restart=always rustdesk/rustdesk-server hbbs + docker run --name hbbs -v $(get_docker_dir)/hbbs/data:/root -td --net=host --restart=always rustdesk/rustdesk-server hbbs } @@ -16934,7 +17128,7 @@ while true; do docker_rum() { - docker run --name hbbr -v /home/docker/hbbr/data:/root -td --net=host --restart=always rustdesk/rustdesk-server hbbr + docker run --name hbbr -v $(get_docker_dir)/hbbr/data:/root -td --net=host --restart=always rustdesk/rustdesk-server hbbr } @@ -16957,7 +17151,7 @@ while true; do docker run -d \ -p ${docker_port}:5000 \ --name registry \ - -v /home/docker/registry:/var/lib/registry \ + -v $(get_docker_dir)/registry:/var/lib/registry \ -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \ --restart=always \ registry:2 @@ -16980,7 +17174,7 @@ while true; do docker_rum() { - docker run -d --name ghproxy --restart=always -p ${docker_port}:8080 -v /home/docker/ghproxy/config:/data/ghproxy/config wjqserver/ghproxy:latest + docker run -d --name ghproxy --restart=always -p ${docker_port}:8080 -v $(get_docker_dir)/ghproxy/config:/data/ghproxy/config wjqserver/ghproxy:latest } @@ -17007,6 +17201,7 @@ while true; do clear ip_address echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip echo "初始用户名密码均为: admin" } @@ -17025,7 +17220,7 @@ while true; do docker rmi -f prom/prometheus:latest docker rmi -f grafana/grafana:latest - rm -rf /home/docker/monitoring + rm -rf $(get_docker_dir)/monitoring echo "应用已卸载" } @@ -17097,7 +17292,7 @@ while true; do docker_rum() { docker run -d --restart=always -p ${docker_port}:5000 \ - -v /home/docker/datastore:/datastore \ + -v $(get_docker_dir)/datastore:/datastore \ --name changedetection dgtlmoon/changedetection.io:latest } @@ -17130,7 +17325,7 @@ while true; do docker run -d --name dpanel --restart=always \ -p ${docker_port}:8080 -e APP_NAME=dpanel \ -v /var/run/docker.sock:/var/run/docker.sock \ - -v /home/docker/dpanel:/dpanel \ + -v $(get_docker_dir)/dpanel:/dpanel \ dpanel/dpanel:lite } @@ -17151,7 +17346,7 @@ while true; do docker_rum() { - docker run -d -p ${docker_port}:8080 -v /home/docker/ollama:/root/.ollama -v /home/docker/ollama/open-webui:/app/backend/data --name ollama --restart=always ghcr.io/open-webui/open-webui:ollama + docker run -d -p ${docker_port}:8080 -v $(get_docker_dir)/ollama:/root/.ollama -v $(get_docker_dir)/ollama/open-webui:/app/backend/data --name ollama --restart=always ghcr.io/open-webui/open-webui:ollama } @@ -17203,7 +17398,7 @@ while true; do docker_rum() { - docker run -d -p ${docker_port}:8080 -v /home/docker/ollama:/root/.ollama -v /home/docker/ollama/open-webui:/app/backend/data --name ollama --restart=always ghcr.io/open-webui/open-webui:ollama + docker run -d -p ${docker_port}:8080 -v $(get_docker_dir)/ollama:/root/.ollama -v $(get_docker_dir)/ollama/open-webui:/app/backend/data --name ollama --restart=always ghcr.io/open-webui/open-webui:ollama } @@ -17227,32 +17422,33 @@ while true; do docker_app_install() { install git - mkdir -p /home/docker/ && cd /home/docker/ && git clone ${gh_proxy}github.com/langgenius/dify.git && cd dify/docker && cp .env.example .env - sed -i "s/^EXPOSE_NGINX_PORT=.*/EXPOSE_NGINX_PORT=${docker_port}/; s/^EXPOSE_NGINX_SSL_PORT=.*/EXPOSE_NGINX_SSL_PORT=8858/" /home/docker/dify/docker/.env + mkdir -p $(get_docker_dir)/ && cd $(get_docker_dir)/ && git clone ${gh_proxy}github.com/langgenius/dify.git && cd dify/docker && cp .env.example .env + sed -i "s/^EXPOSE_NGINX_PORT=.*/EXPOSE_NGINX_PORT=${docker_port}/; s/^EXPOSE_NGINX_SSL_PORT=.*/EXPOSE_NGINX_SSL_PORT=8858/" $(get_docker_dir)/dify/docker/.env docker compose up -d - chown -R 1001:1001 /home/docker/dify/docker/volumes/app/storage - chmod -R 755 /home/docker/dify/docker/volumes/app/storage + chown -R 1001:1001 $(get_docker_dir)/dify/docker/volumes/app/storage + chmod -R 755 $(get_docker_dir)/dify/docker/volumes/app/storage docker compose down docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/dify/docker/ && docker compose down --rmi all - cd /home/docker/dify/ + cd $(get_docker_dir)/dify/docker/ && docker compose down --rmi all + cd $(get_docker_dir)/dify/ git pull ${gh_proxy}github.com/langgenius/dify.git main > /dev/null 2>&1 - sed -i 's/^EXPOSE_NGINX_PORT=.*/EXPOSE_NGINX_PORT=8058/; s/^EXPOSE_NGINX_SSL_PORT=.*/EXPOSE_NGINX_SSL_PORT=8858/' /home/docker/dify/docker/.env - cd /home/docker/dify/docker/ && docker compose up -d + sed -i 's/^EXPOSE_NGINX_PORT=.*/EXPOSE_NGINX_PORT=8058/; s/^EXPOSE_NGINX_SSL_PORT=.*/EXPOSE_NGINX_SSL_PORT=8858/' $(get_docker_dir)/dify/docker/.env + cd $(get_docker_dir)/dify/docker/ && docker compose up -d } docker_app_uninstall() { - cd /home/docker/dify/docker/ && docker compose down --rmi all - rm -rf /home/docker/dify + cd $(get_docker_dir)/dify/docker/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/dify echo "应用已卸载" } @@ -17271,7 +17467,7 @@ while true; do docker_app_install() { install git - mkdir -p /home/docker/ && cd /home/docker/ && git clone ${gh_proxy}github.com/Calcium-Ion/new-api.git && cd new-api + mkdir -p $(get_docker_dir)/ && cd $(get_docker_dir)/ && git clone ${gh_proxy}github.com/Calcium-Ion/new-api.git && cd new-api sed -i -e "s/- \"3000:3000\"/- \"${docker_port}:3000\"/g" \ -e 's/container_name: redis/container_name: redis-new-api/g' \ @@ -17282,12 +17478,13 @@ while true; do docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/new-api/ && docker compose down --rmi all - cd /home/docker/new-api/ + cd $(get_docker_dir)/new-api/ && docker compose down --rmi all + cd $(get_docker_dir)/new-api/ git pull ${gh_proxy}github.com/Calcium-Ion/new-api.git main > /dev/null 2>&1 sed -i -e "s/- \"3000:3000\"/- \"${docker_port}:3000\"/g" \ @@ -17298,13 +17495,14 @@ while true; do docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_uninstall() { - cd /home/docker/new-api/ && docker compose down --rmi all - rm -rf /home/docker/new-api + cd $(get_docker_dir)/new-api/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/new-api echo "应用已卸载" } @@ -17327,6 +17525,7 @@ while true; do curl -sSL ${gh_proxy}github.com/jumpserver/jumpserver/releases/latest/download/quick_start.sh | bash clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip echo "初始用户名: admin" echo "初始密码: ChangeMe" @@ -17389,26 +17588,27 @@ while true; do docker_app_install() { install git - mkdir -p /home/docker/ && cd /home/docker/ && git clone ${gh_proxy}github.com/infiniflow/ragflow.git && cd ragflow/docker + mkdir -p $(get_docker_dir)/ && cd $(get_docker_dir)/ && git clone ${gh_proxy}github.com/infiniflow/ragflow.git && cd ragflow/docker sed -i "s/- 80:80/- ${docker_port}:80/; /- 443:443/d" docker-compose.yml docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/ragflow/docker/ && docker compose down --rmi all - cd /home/docker/ragflow/ + cd $(get_docker_dir)/ragflow/docker/ && docker compose down --rmi all + cd $(get_docker_dir)/ragflow/ git pull ${gh_proxy}github.com/infiniflow/ragflow.git main > /dev/null 2>&1 - cd /home/docker/ragflow/docker/ + cd $(get_docker_dir)/ragflow/docker/ sed -i "s/- 80:80/- ${docker_port}:80/; /- 443:443/d" docker-compose.yml docker compose up -d } docker_app_uninstall() { - cd /home/docker/ragflow/docker/ && docker compose down --rmi all - rm -rf /home/docker/ragflow + cd $(get_docker_dir)/ragflow/docker/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/ragflow echo "应用已卸载" } @@ -17425,7 +17625,7 @@ while true; do docker_rum() { - docker run -d -p ${docker_port}:8080 -v /home/docker/open-webui:/app/backend/data --name open-webui --restart=always ghcr.io/open-webui/open-webui:main + docker run -d -p ${docker_port}:8080 -v $(get_docker_dir)/open-webui:/app/backend/data --name open-webui --restart=always ghcr.io/open-webui/open-webui:main } @@ -17465,13 +17665,13 @@ while true; do docker_rum() { add_yuming - mkdir -p /home/docker/n8n - chmod -R 777 /home/docker/n8n + mkdir -p $(get_docker_dir)/n8n + chmod -R 777 $(get_docker_dir)/n8n docker run -d --name n8n \ --restart=always \ -p ${docker_port}:5678 \ - -v /home/docker/n8n:/home/node/.n8n \ + -v $(get_docker_dir)/n8n:/home/node/.n8n \ -e N8N_HOST=${yuming} \ -e N8N_PORT=5678 \ -e N8N_PROTOCOL=https \ @@ -17507,7 +17707,7 @@ while true; do --name ddns-go \ --restart=always \ -p ${docker_port}:9876 \ - -v /home/docker/ddns-go:/root \ + -v $(get_docker_dir)/ddns-go:/root \ jeessy/ddns-go } @@ -17527,7 +17727,7 @@ while true; do local docker_port=8068 docker_rum() { - docker run -d --name allinssl -p ${docker_port}:8888 -v /home/docker/allinssl/data:/www/allinssl/data -e ALLINSSL_USER=allinssl -e ALLINSSL_PWD=allinssldocker -e ALLINSSL_URL=allinssl allinssl/allinssl:latest + docker run -d --name allinssl -p ${docker_port}:8888 -v $(get_docker_dir)/allinssl/data:/www/allinssl/data -e ALLINSSL_USER=allinssl -e ALLINSSL_PWD=allinssldocker -e ALLINSSL_URL=allinssl allinssl/allinssl:latest } local docker_describe="开源免费的 SSL 证书自动化管理平台" @@ -17547,17 +17747,17 @@ while true; do docker_rum() { - mkdir -p /home/docker/sftpgo/data - mkdir -p /home/docker/sftpgo/config - chown -R 1000:1000 /home/docker/sftpgo + mkdir -p $(get_docker_dir)/sftpgo/data + mkdir -p $(get_docker_dir)/sftpgo/config + chown -R 1000:1000 $(get_docker_dir)/sftpgo docker run -d \ --name sftpgo \ --restart=always \ -p ${docker_port}:8080 \ -p 22022:2022 \ - --mount type=bind,source=/home/docker/sftpgo/data,target=/srv/sftpgo \ - --mount type=bind,source=/home/docker/sftpgo/config,target=/var/lib/sftpgo \ + --mount type=bind,source=$(get_docker_dir)/sftpgo/data,target=/srv/sftpgo \ + --mount type=bind,source=$(get_docker_dir)/sftpgo/config,target=/var/lib/sftpgo \ drakkan/sftpgo:latest } @@ -17579,7 +17779,7 @@ while true; do docker_rum() { - mkdir -p /home/docker/astrbot/data + mkdir -p $(get_docker_dir)/astrbot/data docker run -d \ -p ${docker_port}:6185 \ @@ -17587,7 +17787,7 @@ while true; do -p 6196:6196 \ -p 6199:6199 \ -p 11451:11451 \ - -v /home/docker/astrbot/data:/AstrBot/data \ + -v $(get_docker_dir)/astrbot/data:/AstrBot/data \ --restart=always \ --name astrbot \ soulter/astrbot:latest @@ -17615,8 +17815,8 @@ while true; do --name navidrome \ --restart=always \ --user $(id -u):$(id -g) \ - -v /home/docker/navidrome/music:/music \ - -v /home/docker/navidrome/data:/data \ + -v $(get_docker_dir)/navidrome/music:/music \ + -v $(get_docker_dir)/navidrome/data:/data \ -p ${docker_port}:4533 \ -e ND_LOGLEVEL=info \ deluan/navidrome:latest @@ -17645,7 +17845,7 @@ while true; do --name bitwarden \ --restart=always \ -p ${docker_port}:80 \ - -v /home/docker/bitwarden/data:/data \ + -v $(get_docker_dir)/bitwarden/data:/data \ vaultwarden/server } @@ -17710,33 +17910,34 @@ while true; do read -e -p "输入授权码: " shouquanma - mkdir -p /home/docker/moontv - mkdir -p /home/docker/moontv/config - mkdir -p /home/docker/moontv/data - cd /home/docker/moontv + mkdir -p $(get_docker_dir)/moontv + mkdir -p $(get_docker_dir)/moontv/config + mkdir -p $(get_docker_dir)/moontv/data + cd $(get_docker_dir)/moontv - curl -o /home/docker/moontv/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/moontv-docker-compose.yml - sed -i "s/3000:3000/${docker_port}:3000/g" /home/docker/moontv/docker-compose.yml - sed -i "s|admin_password|${admin_password}|g" /home/docker/moontv/docker-compose.yml - sed -i "s|admin|${admin}|g" /home/docker/moontv/docker-compose.yml - sed -i "s|shouquanma|${shouquanma}|g" /home/docker/moontv/docker-compose.yml - cd /home/docker/moontv/ + curl -o $(get_docker_dir)/moontv/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/moontv-docker-compose.yml + sed -i "s/3000:3000/${docker_port}:3000/g" $(get_docker_dir)/moontv/docker-compose.yml + sed -i "s|admin_password|${admin_password}|g" $(get_docker_dir)/moontv/docker-compose.yml + sed -i "s|admin|${admin}|g" $(get_docker_dir)/moontv/docker-compose.yml + sed -i "s|shouquanma|${shouquanma}|g" $(get_docker_dir)/moontv/docker-compose.yml + cd $(get_docker_dir)/moontv/ docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/moontv/ && docker compose down --rmi all - cd /home/docker/moontv/ && docker compose up -d + cd $(get_docker_dir)/moontv/ && docker compose down --rmi all + cd $(get_docker_dir)/moontv/ && docker compose up -d } docker_app_uninstall() { - cd /home/docker/moontv/ && docker compose down --rmi all - rm -rf /home/docker/moontv + cd $(get_docker_dir)/moontv/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/moontv echo "应用已卸载" } @@ -17758,7 +17959,7 @@ while true; do --name melody \ --restart=always \ -p ${docker_port}:5566 \ - -v /home/docker/melody/.profile:/app/backend/.profile \ + -v $(get_docker_dir)/melody/.profile:/app/backend/.profile \ foamzou/melody:latest @@ -17819,8 +18020,8 @@ while true; do --privileged \ -e XL_DASHBOARD_USERNAME=${app_use} \ -e XL_DASHBOARD_PASSWORD=${app_passwd} \ - -v /home/docker/xunlei/data:/xunlei/data \ - -v /home/docker/xunlei/downloads:/xunlei/downloads \ + -v $(get_docker_dir)/xunlei/data:/xunlei/data \ + -v $(get_docker_dir)/xunlei/downloads:/xunlei/downloads \ -p ${docker_port}:2345 \ cnk3x/xunlei @@ -17874,11 +18075,11 @@ while true; do docker_rum() { - mkdir -p /home/docker/beszel && \ + mkdir -p $(get_docker_dir)/beszel && \ docker run -d \ --name beszel \ --restart=always \ - -v /home/docker/beszel:/beszel_data \ + -v $(get_docker_dir)/beszel:/beszel_data \ -p ${docker_port}:8090 \ henrygd/beszel @@ -17906,7 +18107,7 @@ while true; do docker_app_install() { install git openssl - mkdir -p /home/docker/linkwarden && cd /home/docker/linkwarden + mkdir -p $(get_docker_dir)/linkwarden && cd $(get_docker_dir)/linkwarden # 下载官方 docker-compose 和 env 文件 curl -O ${gh_proxy}raw.githubusercontent.com/linkwarden/linkwarden/refs/heads/main/docker-compose.yml @@ -17925,19 +18126,20 @@ while true; do echo "ADMIN_EMAIL=${ADMIN_EMAIL}" >> .env echo "ADMIN_PASSWORD=${ADMIN_PASSWORD}" >> .env - sed -i "s/3000:3000/${docker_port}:3000/g" /home/docker/linkwarden/docker-compose.yml + sed -i "s/3000:3000/${docker_port}:3000/g" $(get_docker_dir)/linkwarden/docker-compose.yml # 启动容器 docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/linkwarden && docker compose down --rmi all + cd $(get_docker_dir)/linkwarden && docker compose down --rmi all curl -O ${gh_proxy}raw.githubusercontent.com/linkwarden/linkwarden/refs/heads/main/docker-compose.yml curl -L ${gh_proxy}raw.githubusercontent.com/linkwarden/linkwarden/refs/heads/main/.env.sample -o ".env.new" @@ -17950,14 +18152,14 @@ while true; do echo "MEILI_MASTER_KEY=$MEILI_MASTER_KEY" >> .env echo "ADMIN_EMAIL=$ADMIN_EMAIL" >> .env echo "ADMIN_PASSWORD=$ADMIN_PASSWORD" >> .env - sed -i "s/3000:3000/${docker_port}:3000/g" /home/docker/linkwarden/docker-compose.yml + sed -i "s/3000:3000/${docker_port}:3000/g" $(get_docker_dir)/linkwarden/docker-compose.yml docker compose up -d } docker_app_uninstall() { - cd /home/docker/linkwarden && docker compose down --rmi all - rm -rf /home/docker/linkwarden + cd $(get_docker_dir)/linkwarden && docker compose down --rmi all + rm -rf $(get_docker_dir)/linkwarden echo "应用已卸载" } @@ -17979,7 +18181,7 @@ while true; do docker_app_install() { add_yuming - mkdir -p /home/docker/jitsi && cd /home/docker/jitsi + mkdir -p $(get_docker_dir)/jitsi && cd $(get_docker_dir)/jitsi wget $(wget -q -O - https://api.github.com/repos/jitsi/docker-jitsi-meet/releases/latest | grep zip | cut -d\" -f4) unzip "$(ls -t | head -n 1)" cd "$(ls -dt */ | head -n 1)" @@ -17996,7 +18198,7 @@ while true; do } docker_app_update() { - cd /home/docker/jitsi + cd $(get_docker_dir)/jitsi cd "$(ls -dt */ | head -n 1)" docker compose down --rmi all docker compose up -d @@ -18004,10 +18206,10 @@ while true; do } docker_app_uninstall() { - cd /home/docker/jitsi + cd $(get_docker_dir)/jitsi cd "$(ls -dt */ | head -n 1)" docker compose down --rmi all - rm -rf /home/docker/jitsi + rm -rf $(get_docker_dir)/jitsi echo "应用已卸载" } @@ -18028,11 +18230,11 @@ while true; do read -e -p "设置${docker_name}的登录密钥(sk-开头字母和数字组合)如: sk-159kejilionyyds163: " app_passwd - mkdir -p /home/docker/gpt-load && \ + mkdir -p $(get_docker_dir)/gpt-load && \ docker run -d --name gpt-load \ -p ${docker_port}:3001 \ -e AUTH_KEY=${app_passwd} \ - -v "/home/docker/gpt-load/data":/app/data \ + -v "$(get_docker_dir)/gpt-load/data":/app/data \ tbphp/gpt-load:latest } @@ -18057,11 +18259,11 @@ while true; do docker_rum() { - mkdir -p /home/docker/komari && \ + mkdir -p $(get_docker_dir)/komari && \ docker run -d \ --name komari \ -p ${docker_port}:25774 \ - -v /home/docker/komari:/app/data \ + -v $(get_docker_dir)/komari:/app/data \ -e ADMIN_USERNAME=admin \ -e ADMIN_PASSWORD=1212156 \ -e TZ=Asia/Shanghai \ @@ -18090,10 +18292,10 @@ while true; do docker_rum() { - mkdir -p /home/docker/wallos && \ + mkdir -p $(get_docker_dir)/wallos && \ docker run -d --name wallos \ - -v /home/docker/wallos/db:/var/www/html/db \ - -v /home/docker/wallos/logos:/var/www/html/images/uploads/logos \ + -v $(get_docker_dir)/wallos/db:/var/www/html/db \ + -v $(get_docker_dir)/wallos/logos:/var/www/html/images/uploads/logos \ -e TZ=UTC \ -p ${docker_port}:80 \ --restart=always \ @@ -18122,28 +18324,29 @@ while true; do docker_app_install() { install git openssl wget - mkdir -p /home/docker/${docker_name} && cd /home/docker/${docker_name} + mkdir -p $(get_docker_dir)/${docker_name} && cd $(get_docker_dir)/${docker_name} wget -O docker-compose.yml ${gh_proxy}github.com/immich-app/immich/releases/latest/download/docker-compose.yml wget -O .env ${gh_proxy}github.com/immich-app/immich/releases/latest/download/example.env - sed -i "s/2283:2283/${docker_port}:2283/g" /home/docker/${docker_name}/docker-compose.yml + sed -i "s/2283:2283/${docker_port}:2283/g" $(get_docker_dir)/${docker_name}/docker-compose.yml docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/${docker_name} && docker compose down --rmi all + cd $(get_docker_dir)/${docker_name} && docker compose down --rmi all docker_app_install } docker_app_uninstall() { - cd /home/docker/${docker_name} && docker compose down --rmi all - rm -rf /home/docker/${docker_name} + cd $(get_docker_dir)/${docker_name} && docker compose down --rmi all + rm -rf $(get_docker_dir)/${docker_name} echo "应用已卸载" } @@ -18162,15 +18365,15 @@ while true; do docker_rum() { - mkdir -p /home/docker/jellyfin/media - chmod -R 777 /home/docker/jellyfin + mkdir -p $(get_docker_dir)/jellyfin/media + chmod -R 777 $(get_docker_dir)/jellyfin docker run -d \ --name jellyfin \ --user root \ - --volume /home/docker/jellyfin/config:/config \ - --volume /home/docker/jellyfin/cache:/cache \ - --mount type=bind,source=/home/docker/jellyfin/media,target=/media \ + --volume $(get_docker_dir)/jellyfin/config:/config \ + --volume $(get_docker_dir)/jellyfin/cache:/cache \ + --mount type=bind,source=$(get_docker_dir)/jellyfin/media,target=/media \ -p ${docker_port}:8096 \ -p 7359:7359/udp \ --restart=always \ @@ -18200,7 +18403,7 @@ while true; do docker run -d \ --name synctv \ - -v /home/docker/synctv:/root/.synctv \ + -v $(get_docker_dir)/synctv:/root/.synctv \ -p ${docker_port}:8080 \ --restart=always \ synctvorg/synctv @@ -18230,7 +18433,7 @@ while true; do --name owncast \ -p ${docker_port}:8080 \ -p 1935:1935 \ - -v /home/docker/owncast/data:/app/data \ + -v $(get_docker_dir)/owncast/data:/app/data \ --restart=always \ owncast/owncast:latest @@ -18260,7 +18463,7 @@ while true; do docker run -d \ --name file-code-box \ -p ${docker_port}:12345 \ - -v /home/docker/file-code-box/data:/app/data \ + -v $(get_docker_dir)/file-code-box/data:/app/data \ --restart=always \ lanol/filecodebox:latest @@ -18289,9 +18492,9 @@ while true; do add_yuming - if [ ! -d /home/docker/matrix/data ]; then + if [ ! -d $(get_docker_dir)/matrix/data ]; then docker run --rm \ - -v /home/docker/matrix/data:/data \ + -v $(get_docker_dir)/matrix/data:/data \ -e SYNAPSE_SERVER_NAME=${yuming} \ -e SYNAPSE_REPORT_STATS=yes \ --name matrix \ @@ -18300,7 +18503,7 @@ while true; do docker run -d \ --name matrix \ - -v /home/docker/matrix/data:/data \ + -v $(get_docker_dir)/matrix/data:/data \ -p ${docker_port}:8008 \ --restart=always \ matrixdotorg/synapse:latest @@ -18310,10 +18513,10 @@ while true; do http://localhost:8008 \ -c /data/homeserver.yaml - sed -i '/^enable_registration:/d' /home/docker/matrix/data/homeserver.yaml - sed -i '/^# vim:ft=yaml/i enable_registration: true' /home/docker/matrix/data/homeserver.yaml - sed -i '/^enable_registration_without_verification:/d' /home/docker/matrix/data/homeserver.yaml - sed -i '/^# vim:ft=yaml/i enable_registration_without_verification: true' /home/docker/matrix/data/homeserver.yaml + sed -i '/^enable_registration:/d' $(get_docker_dir)/matrix/data/homeserver.yaml + sed -i '/^# vim:ft=yaml/i enable_registration: true' $(get_docker_dir)/matrix/data/homeserver.yaml + sed -i '/^enable_registration_without_verification:/d' $(get_docker_dir)/matrix/data/homeserver.yaml + sed -i '/^# vim:ft=yaml/i enable_registration_without_verification: true' $(get_docker_dir)/matrix/data/homeserver.yaml docker restart matrix @@ -18346,31 +18549,32 @@ while true; do docker_app_install() { - mkdir -p /home/docker/gitea - mkdir -p /home/docker/gitea/gitea - mkdir -p /home/docker/gitea/data - mkdir -p /home/docker/gitea/postgres - cd /home/docker/gitea + mkdir -p $(get_docker_dir)/gitea + mkdir -p $(get_docker_dir)/gitea/gitea + mkdir -p $(get_docker_dir)/gitea/data + mkdir -p $(get_docker_dir)/gitea/postgres + cd $(get_docker_dir)/gitea - curl -o /home/docker/gitea/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/gitea-docker-compose.yml - sed -i "s/3000:3000/${docker_port}:3000/g" /home/docker/gitea/docker-compose.yml - cd /home/docker/gitea/ + curl -o $(get_docker_dir)/gitea/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/gitea-docker-compose.yml + sed -i "s/3000:3000/${docker_port}:3000/g" $(get_docker_dir)/gitea/docker-compose.yml + cd $(get_docker_dir)/gitea/ docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/gitea/ && docker compose down --rmi all - cd /home/docker/gitea/ && docker compose up -d + cd $(get_docker_dir)/gitea/ && docker compose down --rmi all + cd $(get_docker_dir)/gitea/ && docker compose up -d } docker_app_uninstall() { - cd /home/docker/gitea/ && docker compose down --rmi all - rm -rf /home/docker/gitea + cd $(get_docker_dir)/gitea/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/gitea echo "应用已卸载" } @@ -18394,8 +18598,8 @@ while true; do --name filebrowser \ --restart=always \ -p ${docker_port}:8080 \ - -v /home/docker/filebrowser/data:/data \ - -v /home/docker/filebrowser/config:/config \ + -v $(get_docker_dir)/filebrowser/data:/data \ + -v $(get_docker_dir)/filebrowser/config:/config \ -e FB_BASEURL=/filebrowser \ hurlenko/filebrowser @@ -18422,7 +18626,7 @@ while true; do docker run -d \ --name ${docker_name} \ --restart=always \ - -v /home/docker/${docker_name}:/data \ + -v $(get_docker_dir)/${docker_name}:/data \ -p ${docker_port}:5000 \ ${docker_img} /data -A @@ -18452,8 +18656,8 @@ while true; do docker run -d \ --name ${docker_name} \ --restart=always \ - -v /home/docker/${docker_name}/downloads:/app/Downloads \ - -v /home/docker/${docker_name}/storage:/app/storage \ + -v $(get_docker_dir)/${docker_name}/downloads:/app/Downloads \ + -v $(get_docker_dir)/${docker_name}/storage:/app/storage \ -p ${docker_port}:9999 \ ${docker_img} -u ${app_use} -p ${app_passwd} @@ -18483,32 +18687,33 @@ while true; do docker_app_install() { - mkdir -p /home/docker/paperless - mkdir -p /home/docker/paperless/export - mkdir -p /home/docker/paperless/consume - cd /home/docker/paperless + mkdir -p $(get_docker_dir)/paperless + mkdir -p $(get_docker_dir)/paperless/export + mkdir -p $(get_docker_dir)/paperless/consume + cd $(get_docker_dir)/paperless - curl -o /home/docker/paperless/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/paperless-ngx/paperless-ngx/refs/heads/main/docker/compose/docker-compose.postgres-tika.yml - curl -o /home/docker/paperless/docker-compose.env ${gh_proxy}raw.githubusercontent.com/paperless-ngx/paperless-ngx/refs/heads/main/docker/compose/.env + curl -o $(get_docker_dir)/paperless/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/paperless-ngx/paperless-ngx/refs/heads/main/docker/compose/docker-compose.postgres-tika.yml + curl -o $(get_docker_dir)/paperless/docker-compose.env ${gh_proxy}raw.githubusercontent.com/paperless-ngx/paperless-ngx/refs/heads/main/docker/compose/.env - sed -i "s/8000:8000/${docker_port}:8000/g" /home/docker/paperless/docker-compose.yml - cd /home/docker/paperless + sed -i "s/8000:8000/${docker_port}:8000/g" $(get_docker_dir)/paperless/docker-compose.yml + cd $(get_docker_dir)/paperless docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/paperless/ && docker compose down --rmi all + cd $(get_docker_dir)/paperless/ && docker compose down --rmi all docker_app_install } docker_app_uninstall() { - cd /home/docker/paperless/ && docker compose down --rmi all - rm -rf /home/docker/paperless + cd $(get_docker_dir)/paperless/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/paperless echo "应用已卸载" } @@ -18533,16 +18738,16 @@ while true; do add_yuming - mkdir -p /home/docker/2fauth - mkdir -p /home/docker/2fauth/data - chmod -R 777 /home/docker/2fauth/ - cd /home/docker/2fauth + mkdir -p $(get_docker_dir)/2fauth + mkdir -p $(get_docker_dir)/2fauth/data + chmod -R 777 $(get_docker_dir)/2fauth/ + cd $(get_docker_dir)/2fauth - curl -o /home/docker/2fauth/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/2fauth-docker-compose.yml + curl -o $(get_docker_dir)/2fauth/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/2fauth-docker-compose.yml - sed -i "s/8000:8000/${docker_port}:8000/g" /home/docker/2fauth/docker-compose.yml - sed -i "s/yuming.com/${yuming}/g" /home/docker/2fauth/docker-compose.yml - cd /home/docker/2fauth + sed -i "s/8000:8000/${docker_port}:8000/g" $(get_docker_dir)/2fauth/docker-compose.yml + sed -i "s/yuming.com/${yuming}/g" $(get_docker_dir)/2fauth/docker-compose.yml + cd $(get_docker_dir)/2fauth docker compose up -d ldnmp_Proxy ${yuming} 127.0.0.1 ${docker_port} @@ -18550,19 +18755,20 @@ while true; do clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/2fauth/ && docker compose down --rmi all + cd $(get_docker_dir)/2fauth/ && docker compose down --rmi all docker_app_install } docker_app_uninstall() { - cd /home/docker/2fauth/ && docker compose down --rmi all - rm -rf /home/docker/2fauth + cd $(get_docker_dir)/2fauth/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/2fauth echo "应用已卸载" } @@ -18606,7 +18812,7 @@ while true; do -e ALLOWEDIPS=${NETWORK}/24 \ -e PERSISTENTKEEPALIVE_PEERS=all \ -e LOG_CONFS=true \ - -v /home/docker/wireguard/config:/config \ + -v $(get_docker_dir)/wireguard/config:/config \ -v /lib/modules:/lib/modules \ --restart=always \ lscr.io/linuxserver/wireguard:latest @@ -18688,9 +18894,9 @@ while true; do docker_rum() { - mkdir -p /home/docker/wireguard/config/ + mkdir -p $(get_docker_dir)/wireguard/config/ - local CONFIG_FILE="/home/docker/wireguard/config/wg0.conf" + local CONFIG_FILE="$(get_docker_dir)/wireguard/config/wg0.conf" # 创建目录(如果不存在) mkdir -p "$(dirname "$CONFIG_FILE")" @@ -18726,7 +18932,7 @@ while true; do --network host \ --cap-add NET_ADMIN \ --cap-add SYS_MODULE \ - -v /home/docker/wireguard/config:/config \ + -v $(get_docker_dir)/wireguard/config:/config \ -v /lib/modules:/lib/modules:ro \ --restart=always \ kjlion/wireguard:alpine @@ -18768,34 +18974,35 @@ while true; do read -e -p "设置内存大小 (默认 4G): " RAM_SIZE local RAM_SIZE=${RAM_SIZE:-4} - mkdir -p /home/docker/dsm - mkdir -p /home/docker/dsm/dev - chmod -R 777 /home/docker/dsm/ - cd /home/docker/dsm + mkdir -p $(get_docker_dir)/dsm + mkdir -p $(get_docker_dir)/dsm/dev + chmod -R 777 $(get_docker_dir)/dsm/ + cd $(get_docker_dir)/dsm - curl -o /home/docker/dsm/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/dsm-docker-compose.yml + curl -o $(get_docker_dir)/dsm/docker-compose.yml ${gh_proxy}raw.githubusercontent.com/kejilion/docker/main/dsm-docker-compose.yml - sed -i "s/5000:5000/${docker_port}:5000/g" /home/docker/dsm/docker-compose.yml - sed -i "s|CPU_CORES: "2"|CPU_CORES: "${CPU_CORES}"|g" /home/docker/dsm/docker-compose.yml - sed -i "s|RAM_SIZE: "2G"|RAM_SIZE: "${RAM_SIZE}G"|g" /home/docker/dsm/docker-compose.yml - cd /home/docker/dsm + sed -i "s/5000:5000/${docker_port}:5000/g" $(get_docker_dir)/dsm/docker-compose.yml + sed -i "s|CPU_CORES: "2"|CPU_CORES: "${CPU_CORES}"|g" $(get_docker_dir)/dsm/docker-compose.yml + sed -i "s|RAM_SIZE: "2G"|RAM_SIZE: "${RAM_SIZE}G"|g" $(get_docker_dir)/dsm/docker-compose.yml + cd $(get_docker_dir)/dsm docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/dsm/ && docker compose down --rmi all + cd $(get_docker_dir)/dsm/ && docker compose down --rmi all docker_app_install } docker_app_uninstall() { - cd /home/docker/dsm/ && docker compose down --rmi all - rm -rf /home/docker/dsm + cd $(get_docker_dir)/dsm/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/dsm echo "应用已卸载" } @@ -18821,7 +19028,7 @@ while true; do -p 22000:22000/tcp \ -p 22000:22000/udp \ -p 21027:21027/udp \ - -v /home/docker/syncthing:/var/syncthing \ + -v $(get_docker_dir)/syncthing:/var/syncthing \ syncthing/syncthing:latest } @@ -18846,27 +19053,28 @@ while true; do docker_app_install() { install git - mkdir -p /home/docker/ && cd /home/docker/ && git clone ${gh_proxy}github.com/harry0703/MoneyPrinterTurbo.git && cd MoneyPrinterTurbo/ - sed -i "s/8501:8501/${docker_port}:8501/g" /home/docker/MoneyPrinterTurbo/docker-compose.yml + mkdir -p $(get_docker_dir)/ && cd $(get_docker_dir)/ && git clone ${gh_proxy}github.com/harry0703/MoneyPrinterTurbo.git && cd MoneyPrinterTurbo/ + sed -i "s/8501:8501/${docker_port}:8501/g" $(get_docker_dir)/MoneyPrinterTurbo/docker-compose.yml docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/MoneyPrinterTurbo/ && docker compose down --rmi all - cd /home/docker/MoneyPrinterTurbo/ + cd $(get_docker_dir)/MoneyPrinterTurbo/ && docker compose down --rmi all + cd $(get_docker_dir)/MoneyPrinterTurbo/ git pull ${gh_proxy}github.com/harry0703/MoneyPrinterTurbo.git main > /dev/null 2>&1 - sed -i "s/8501:8501/${docker_port}:8501/g" /home/docker/MoneyPrinterTurbo/docker-compose.yml - cd /home/docker/MoneyPrinterTurbo/ && docker compose up -d + sed -i "s/8501:8501/${docker_port}:8501/g" $(get_docker_dir)/MoneyPrinterTurbo/docker-compose.yml + cd $(get_docker_dir)/MoneyPrinterTurbo/ && docker compose up -d } docker_app_uninstall() { - cd /home/docker/MoneyPrinterTurbo/ && docker compose down --rmi all - rm -rf /home/docker/MoneyPrinterTurbo + cd $(get_docker_dir)/MoneyPrinterTurbo/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/MoneyPrinterTurbo echo "应用已卸载" } @@ -18888,7 +19096,7 @@ while true; do docker run -d --restart=always \ -p ${docker_port}:3000 \ --name vocechat-server \ - -v /home/docker/vocechat/data:/home/vocechat-server/data \ + -v $(get_docker_dir)/vocechat/data:/home/vocechat-server/data \ privoce/vocechat-server:latest } @@ -18914,28 +19122,29 @@ while true; do docker_app_install() { install git - mkdir -p /home/docker/ && cd /home/docker/ && git clone ${gh_proxy}github.com/umami-software/umami.git && cd umami - sed -i "s/3000:3000/${docker_port}:3000/g" /home/docker/umami/docker-compose.yml + mkdir -p $(get_docker_dir)/ && cd $(get_docker_dir)/ && git clone ${gh_proxy}github.com/umami-software/umami.git && cd umami + sed -i "s/3000:3000/${docker_port}:3000/g" $(get_docker_dir)/umami/docker-compose.yml docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip echo "初始用户名: admin" echo "初始密码: umami" } docker_app_update() { - cd /home/docker/umami/ && docker compose down --rmi all - cd /home/docker/umami/ + cd $(get_docker_dir)/umami/ && docker compose down --rmi all + cd $(get_docker_dir)/umami/ git pull ${gh_proxy}github.com/umami-software/umami.git main > /dev/null 2>&1 - sed -i "s/8501:8501/${docker_port}:8501/g" /home/docker/umami/docker-compose.yml - cd /home/docker/umami/ && docker compose up -d + sed -i "s/8501:8501/${docker_port}:8501/g" $(get_docker_dir)/umami/docker-compose.yml + cd $(get_docker_dir)/umami/ && docker compose up -d } docker_app_uninstall() { - cd /home/docker/umami/ && docker compose down --rmi all - rm -rf /home/docker/umami + cd $(get_docker_dir)/umami/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/umami echo "应用已卸载" } @@ -18962,7 +19171,7 @@ while true; do docker run -d \ --name siyuan \ --restart=always \ - -v /home/docker/siyuan/workspace:/siyuan/workspace \ + -v $(get_docker_dir)/siyuan/workspace:/siyuan/workspace \ -p ${docker_port}:6806 \ -e PUID=1001 \ -e PGID=1002 \ @@ -19022,8 +19231,8 @@ while true; do --name pansou \ --restart=always \ -p ${docker_port}:80 \ - -v /home/docker/pansou/data:/app/data \ - -v /home/docker/pansou/logs:/app/logs \ + -v $(get_docker_dir)/pansou/data:/app/data \ + -v $(get_docker_dir)/pansou/logs:/app/logs \ -e ENABLED_PLUGINS="hunhepan,jikepan,panwiki,pansearch,panta,qupansou, susu,thepiratebay,wanou,xuexizhinan,panyq,zhizhen,labi,muou,ouge,shandian, duoduo,huban,cyg,erxiao,miaoso,fox4k,pianku,clmao,wuji,cldi,xiaozhang, @@ -19057,26 +19266,27 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ docker_app_install() { install git - mkdir -p /home/docker/ && cd /home/docker/ && git clone ${gh_proxy}github.com/langbot-app/LangBot && cd LangBot/docker - sed -i "s/5300:5300/${docker_port}:5300/g" /home/docker/LangBot/docker/docker-compose.yaml + mkdir -p $(get_docker_dir)/ && cd $(get_docker_dir)/ && git clone ${gh_proxy}github.com/langbot-app/LangBot && cd LangBot/docker + sed -i "s/5300:5300/${docker_port}:5300/g" $(get_docker_dir)/LangBot/docker/docker-compose.yaml docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/LangBot/docker && docker compose down --rmi all - cd /home/docker/LangBot/ + cd $(get_docker_dir)/LangBot/docker && docker compose down --rmi all + cd $(get_docker_dir)/LangBot/ git pull ${gh_proxy}github.com/langbot-app/LangBot main > /dev/null 2>&1 - sed -i "s/5300:5300/${docker_port}:5300/g" /home/docker/LangBot/docker/docker-compose.yaml - cd /home/docker/LangBot/docker/ && docker compose up -d + sed -i "s/5300:5300/${docker_port}:5300/g" $(get_docker_dir)/LangBot/docker/docker-compose.yaml + cd $(get_docker_dir)/LangBot/docker/ && docker compose up -d } docker_app_uninstall() { - cd /home/docker/LangBot/docker/ && docker compose down --rmi all - rm -rf /home/docker/LangBot + cd $(get_docker_dir)/LangBot/docker/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/LangBot echo "应用已卸载" } @@ -19097,10 +19307,10 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ docker run -d --name=zfile --restart=always \ -p ${docker_port}:8080 \ - -v /home/docker/zfile/db:/root/.zfile-v4/db \ - -v /home/docker/zfile/logs:/root/.zfile-v4/logs \ - -v /home/docker/zfile/file:/data/file \ - -v /home/docker/zfile/application.properties:/root/.zfile-v4/application.properties \ + -v $(get_docker_dir)/zfile/db:/root/.zfile-v4/db \ + -v $(get_docker_dir)/zfile/logs:/root/.zfile-v4/logs \ + -v $(get_docker_dir)/zfile/file:/data/file \ + -v $(get_docker_dir)/zfile/application.properties:/root/.zfile-v4/application.properties \ zhaojun1998/zfile:latest @@ -19127,26 +19337,27 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ docker_app_install() { install git - mkdir -p /home/docker/ && cd /home/docker/ && git clone ${gh_proxy}github.com/karakeep-app/karakeep.git && cd karakeep/docker && cp .env.sample .env - sed -i "s/3000:3000/${docker_port}:3000/g" /home/docker/karakeep/docker/docker-compose.yml + mkdir -p $(get_docker_dir)/ && cd $(get_docker_dir)/ && git clone ${gh_proxy}github.com/karakeep-app/karakeep.git && cd karakeep/docker && cp .env.sample .env + sed -i "s/3000:3000/${docker_port}:3000/g" $(get_docker_dir)/karakeep/docker/docker-compose.yml docker compose up -d clear echo "已经安装完成" + show_app_info "$docker_name" check_docker_app_ip } docker_app_update() { - cd /home/docker/karakeep/docker/ && docker compose down --rmi all - cd /home/docker/karakeep/ + cd $(get_docker_dir)/karakeep/docker/ && docker compose down --rmi all + cd $(get_docker_dir)/karakeep/ git pull ${gh_proxy}github.com/karakeep-app/karakeep.git main > /dev/null 2>&1 - sed -i "s/3000:3000/${docker_port}:3000/g" /home/docker/karakeep/docker/docker-compose.yml - cd /home/docker/karakeep/docker/ && docker compose up -d + sed -i "s/3000:3000/${docker_port}:3000/g" $(get_docker_dir)/karakeep/docker/docker-compose.yml + cd $(get_docker_dir)/karakeep/docker/ && docker compose up -d } docker_app_uninstall() { - cd /home/docker/karakeep/docker/ && docker compose down --rmi all - rm -rf /home/docker/karakeep + cd $(get_docker_dir)/karakeep/docker/ && docker compose down --rmi all + rm -rf $(get_docker_dir)/karakeep echo "应用已卸载" } @@ -19167,7 +19378,7 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ docker run -d --name=${docker_name} --restart=always \ -p ${docker_port}:3000 \ - -v /home/docker/convertx:/app/data \ + -v $(get_docker_dir)/convertx:/app/data \ ${docker_img} } @@ -19194,7 +19405,7 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ docker run -d --name=${docker_name} --restart=always \ --network host \ - -v /home/docker/lucky/conf:/app/conf \ + -v $(get_docker_dir)/lucky/conf:/app/conf \ -v /var/run/docker.sock:/var/run/docker.sock \ ${docker_img} @@ -19227,7 +19438,7 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ docker run -d --name=${docker_name} --restart=always \ -p ${docker_port}:5800 \ - -v /home/docker/firefox:/config:rw \ + -v $(get_docker_dir)/firefox:/config:rw \ -e ENABLE_CJK_FONT=1 \ -e WEB_AUDIO=1 \ -e VNC_PASSWORD="${admin_password}" \ diff --git a/kr/kejilion.sh b/kr/kejilion.sh index 2615ac69a..fb77fb087 100644 --- a/kr/kejilion.sh +++ b/kr/kejilion.sh @@ -1,5 +1,5 @@ #!/bin/bash -sh_v="4.4.9" +sh_v="4.4.10" gl_hui='\e[37m' @@ -1099,7 +1099,7 @@ iptables_panel() { echo "3. 모든 포트를 엽니다. 4. 모든 포트를 닫습니다." echo "------------------------" echo "5. IP 화이트리스트 6. IP 블랙리스트" - echo "7. 지정된 IP를 삭제합니다." + echo "7. 지정된 IP 지우기" echo "------------------------" echo "11. PING 허용 12. PING 비활성화" echo "------------------------" @@ -1268,7 +1268,7 @@ check_swap() { local swap_total=$(free -m | awk 'NR==3{print $2}') -# 가상 메모리를 만들어야 하는지 확인 +# 가상 메모리를 생성해야 하는지 결정 [ "$swap_total" -gt 0 ] || add_swap 1024 @@ -1852,7 +1852,7 @@ check_waf_status() { if grep -q "^\s*#\s*modsecurity on;" /home/web/nginx.conf; then waf_status="" elif grep -q "modsecurity on;" /home/web/nginx.conf; then - waf_status="WAF가 켜져 있습니다" + waf_status="WAF가 켜져 있습니다." else waf_status="" fi @@ -2238,7 +2238,7 @@ web_security() { 22) send_stats "고부하로 5초 쉴드 가능" - echo -e "${gl_huang}웹사이트는 5분마다 자동으로 감지합니다. 높은 부하를 감지하면 자동으로 쉴드가 열리고, 낮은 부하가 감지되면 자동으로 5초 동안 쉴드가 닫힙니다.${gl_bai}" + echo -e "${gl_huang}웹사이트는 5분마다 자동으로 감지합니다. 고부하를 감지하면 자동으로 실드를 열고, 저부하를 감지하면 자동으로 5초 동안 실드를 닫습니다.${gl_bai}" echo "--------------" echo "CF 매개변수 가져오기:" echo -e "cf 백엔드 오른쪽 상단에 있는 내 프로필로 이동하여 왼쪽에 있는 API 토큰을 선택하고${gl_huang}Global API Key${gl_bai}" @@ -2324,7 +2324,7 @@ check_nginx_compression() { # zstd가 켜져 있고 주석 처리가 해제되어 있는지 확인하세요. (전체 줄은 zstd on으로 시작됩니다.) if grep -qE '^\s*zstd\s+on;' "$CONFIG_FILE"; then - zstd_status="zstd 압축이 활성화되었습니다" + zstd_status="zstd 압축이 켜져 있습니다" else zstd_status="" fi @@ -2504,7 +2504,7 @@ check_docker_app() { # if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "$docker_name"; then # check_docker="${gl_lv}가 ${gl_bai}를 설치했습니다." # else -# check_docker="${gl_hui}이(가) ${gl_bai}" 설치되지 않았습니다. +# check_docker="${gl_hui}가 ${gl_bai}" 설치되지 않았습니다. # fi # } @@ -2559,7 +2559,7 @@ check_docker_image_update() { # 3. 지능형 라우팅 판단 if [[ "$full_image_name" == ghcr.io* ]]; then # --- 시나리오 A: GitHub(ghcr.io)의 미러링 --- - # 웨어하우스 경로를 추출합니다(예: ghcr.io/onexru/oneimg -> onexru/oneimg). + # 예를 들어 ghcr.io/onexru/oneimg -> onexru/oneimg와 같이 웨어하우스 경로를 추출합니다. local repo_path=$(echo "$full_image_name" | sed 's/ghcr.io\///' | cut -d':' -f1) # 참고: ghcr.io의 API는 비교적 복잡합니다. 일반적으로 가장 빠른 방법은 GitHub Repo 릴리스를 확인하는 것입니다. local api_url="https://api.github.com/repos/$repo_path/releases/latest" @@ -2673,7 +2673,7 @@ clear_container_rules() { iptables -D DOCKER-USER -p tcp -d "$container_ip" -j DROP fi - # 특정 IP를 허용하는 규칙 지우기 + # 지정된 IP를 허용하는 규칙을 지웁니다. if iptables -C DOCKER-USER -p tcp -s "$allowed_ip" -d "$container_ip" -j ACCEPT &>/dev/null; then iptables -D DOCKER-USER -p tcp -s "$allowed_ip" -d "$container_ip" -j ACCEPT fi @@ -2692,7 +2692,7 @@ clear_container_rules() { iptables -D DOCKER-USER -p udp -d "$container_ip" -j DROP fi - # 특정 IP를 허용하는 규칙 지우기 + # 지정된 IP를 허용하는 규칙을 지웁니다. if iptables -C DOCKER-USER -p udp -s "$allowed_ip" -d "$container_ip" -j ACCEPT &>/dev/null; then iptables -D DOCKER-USER -p udp -s "$allowed_ip" -d "$container_ip" -j ACCEPT fi @@ -3221,7 +3221,7 @@ f2b_sshd() { # 기본 매개변수 구성: 금지 기간(bantime), 기간(findtime), 재시도 횟수(maxretry) # 설명하다: -# - /etc/fail2ban/jail.d/sshd.local에 대한 쓰기 우선 순위를 지정합니다(기본 감옥 구성을 무시하고 업그레이드 시 손실되기 쉽지 않습니다). +# - /etc/fail2ban/jail.d/sshd.local에 쓰기 우선 순위를 지정합니다(기본 감옥 구성을 덮어쓰며 업그레이드 시 손실되기 쉽지 않습니다). # - Alpine이고 감옥 이름이 다른 경우에도 sshd.local을 작성하세요. Fail2Ban은 감옥 이름에 따라 일치합니다. f2b_basic_config() { root_use @@ -3423,7 +3423,7 @@ ldnmp_web_on() { echo "당신의$webname지어졌습니다!" echo "https://$yuming" echo "------------------------" - echo "$webname설치정보는 다음과 같습니다." + echo "$webname설치 정보는 다음과 같습니다." } @@ -3509,7 +3509,7 @@ ldnmp_Proxy() { check_ip_and_get_access_port "$yuming" if [ -z "$reverseproxy" ]; then - read -e -p "세대 방지 IP를 입력하십시오(기본값은 로컬 IP 127.0.0.1로 설정하려면 Enter를 누르십시오)." reverseproxy + read -e -p "안티 세대 IP를 입력하십시오(기본값은 로컬 IP 127.0.0.1로 설정하려면 Enter를 누르십시오)." reverseproxy reverseproxy=${reverseproxy:-127.0.0.1} fi @@ -3725,7 +3725,7 @@ stream_panel() { ldnmp_Proxy_backend_stream() { clear - webname="스트리밍 4계층 프록시-로드 밸런싱" + webname="스트림 4계층 프록시-로드 밸런싱" send_stats "설치하다$webname" echo "배포 시작$webname" @@ -5055,10 +5055,10 @@ fetch_remote_ssh_keys() { touch "${authorized_keys}" chmod 600 "${authorized_keys}" - # 원본 인증_키 백업 + # 원래 인증된_키 백업 if [[ -f "${authorized_keys}" ]]; then cp "${authorized_keys}" "${authorized_keys}.bak.$(date +%Y%m%d-%H%M%S)" - echo "원래 Authorized_keys 파일이 백업되었습니다." + echo "원본 Authorized_keys 파일이 백업되었습니다." fi # 공개 키 추가(중복 방지) @@ -5637,7 +5637,7 @@ bbrv3() { apt update -y apt install -y linux-xanmod-x64v$version - echo "XanMod 커널이 업데이트되었습니다. 재시작 후 적용" + echo "XanMod 커널이 업데이트되었습니다. 다시 시작한 후 적용" rm -f /etc/apt/sources.list.d/xanmod-release.list rm -f check_x86-64_psabi.sh* @@ -5647,7 +5647,7 @@ bbrv3() { 2) apt purge -y 'linux-*xanmod1*' update-grub - echo "XanMod 커널이 제거되었습니다. 재시작 후 적용" + echo "XanMod 커널이 제거되었습니다. 다시 시작한 후 적용" server_reboot ;; @@ -5701,7 +5701,7 @@ bbrv3() { bbr_on - echo "XanMod 커널이 설치되고 BBR3이 성공적으로 활성화되었습니다. 재시작 후 적용" + echo "XanMod 커널이 설치되고 BBR3이 성공적으로 활성화되었습니다. 다시 시작한 후 적용" rm -f /etc/apt/sources.list.d/xanmod-release.list rm -f check_x86-64_psabi.sh* server_reboot @@ -5790,7 +5790,7 @@ elrepo() { 2) dnf remove -y elrepo-release rpm -qa | grep elrepo | grep kernel | xargs rpm -e --nodeps - echo "elrepo 커널이 제거되었습니다. 재시작 후 적용" + echo "elrepo 커널이 제거되었습니다. 다시 시작한 후 적용" send_stats "Red Hat 커널 제거" server_reboot @@ -5808,7 +5808,7 @@ elrepo() { echo "영상 소개: https://www.bilibili.com/video/BV1mH4y1w7qA?t=529.2" echo "------------------------------------------------" echo "Red Hat 시리즈 배포판 CentOS/RedHat/Alma/Rocky/oracle만 지원" - echo "Linux 커널을 업그레이드하면 시스템 성능과 보안이 향상될 수 있습니다. 가능하다면 시도해 보시고, 프로덕션 환경을 주의해서 업그레이드하시는 것을 추천드립니다!" + echo "Linux 커널을 업그레이드하면 시스템 성능과 보안이 향상될 수 있습니다. 가능하다면 시도해 보시고, 프로덕션 환경도 주의해서 업그레이드하시는 것을 추천드립니다!" echo "------------------------------------------------" read -e -p "계속하시겠습니까? (예/아니요):" choice @@ -5844,7 +5844,7 @@ clamav_freshclam() { clamav_scan() { if [ $# -eq 0 ]; then - echo "스캔할 디렉터리를 지정하세요." + echo "스캔할 디렉터리를 지정하십시오." return fi @@ -5957,7 +5957,7 @@ _kernel_optimize_core() { echo -e "${gl_lv}로 전환하다${mode_name}...${gl_bai}" - # ──장면에 따라 매개변수를 설정합니다── + # ──장면에 따라 매개변수를 설정하세요── local SWAPPINESS DIRTY_RATIO DIRTY_BG_RATIO OVERCOMMIT MIN_FREE_KB VFS_PRESSURE local RMEM_MAX WMEM_MAX TCP_RMEM TCP_WMEM local SOMAXCONN BACKLOG SYN_BACKLOG @@ -6544,7 +6544,7 @@ linux_trash() { clear echo -e "현재 휴지통${trash_status}" - echo -e "활성화한 후에는 중요한 파일이 실수로 삭제되는 것을 방지하기 위해 rm으로 삭제된 파일이 먼저 휴지통에 저장됩니다!" + echo -e "활성화한 후에는 중요한 파일이 실수로 삭제되는 것을 방지하기 위해 rm으로 삭제된 파일이 먼저 휴지통에 들어갑니다!" echo "------------------------------------------------" ls -l --color=auto "$TRASH_DIR" 2>/dev/null || echo "휴지통이 비어 있습니다." echo "------------------------" @@ -7213,7 +7213,7 @@ disk_manager() { send_stats "하드디스크 관리 기능" while true; do clear - echo "하드 드라이브 파티션 관리" + echo "하드 디스크 파티션 관리" echo -e "${gl_huang}이 기능은 내부 테스트 중이므로 프로덕션 환경에서는 사용하면 안 됩니다.${gl_bai}" echo "------------------------" list_partitions @@ -8142,7 +8142,7 @@ docker_ssh_migration() { mkdir -p "$original_path" tar -xzf "$BACKUP_DIR/compose_project_${project_name}.tar.gz" -C "$original_path" - echo -e "${gl_lv}프로젝트 작성 [$project_name]는 다음 위치로 추출되었습니다.$original_path${gl_bai}" + echo -e "${gl_lv}프로젝트 작성 [$project_name]가 다음 위치로 추출되었습니다.$original_path${gl_bai}" cd "$original_path" || return docker compose down || true @@ -8232,7 +8232,7 @@ docker_ssh_migration() { migrate_docker() { send_stats "도커 마이그레이션" install jq - read -e -p "마이그레이션할 백업 디렉터리를 입력하세요." BACKUP_DIR + read -e -p "마이그레이션할 백업 디렉터리를 입력하십시오:" BACKUP_DIR [[ ! -d "$BACKUP_DIR" ]] && { echo -e "${gl_hong}백업 디렉터리가 존재하지 않습니다.${gl_bai}"; return; } kj_ssh_read_host_user_port "대상 서버 IP:" "대상 서버 SSH 사용자 이름 [기본 루트]:" "대상 서버 SSH 포트 [기본값 22]:" "root" "22" @@ -8277,7 +8277,7 @@ docker_ssh_migration() { echo -e "1. 도커 프로젝트 백업" echo -e "2. 도커 프로젝트 마이그레이션" echo -e "3. 도커 프로젝트 복원" - echo -e "4. Docker 프로젝트의 백업 파일을 삭제합니다." + echo -e "4. docker 프로젝트 백업 파일 삭제" echo "------------------------" echo -e "0. 이전 메뉴로 돌아가기" echo "------------------------" @@ -8477,7 +8477,7 @@ linux_docker() { ;; 2) - read -e -p "삭제 볼륨 이름을 입력하십시오(여러 볼륨 이름을 공백으로 구분하십시오):" dockerjuans + read -e -p "삭제 볼륨 이름을 입력하세요(여러 볼륨 이름을 공백으로 구분하세요):" dockerjuans for dockerjuan in $dockerjuans; do docker volume rm $dockerjuan @@ -8792,7 +8792,7 @@ linux_Oracle() { 1) clear echo "활성 스크립트: CPU 사용량 10-20% 메모리 사용량 20%" - read -e -p "설치하시겠습니까? (예/아니요):" choice + read -e -p "정말로 설치하시겠습니까? (예/아니요):" choice case "$choice" in [Yy]) @@ -10783,7 +10783,7 @@ EOF } - + openclaw_api_manage_list() { local config_file="${HOME}/.openclaw/openclaw.json" send_stats "OpenClaw API 목록" @@ -11500,7 +11500,7 @@ PY if command -v gum >/dev/null 2>&1; then return 0 fi - + if command -v apt >/dev/null 2>&1; then mkdir -p /etc/apt/keyrings curl -fsSL https://repo.charm.sh/apt/gpg.key | gpg --dearmor -o /etc/apt/keyrings/charm.gpg @@ -11528,7 +11528,7 @@ REPO } - + change_model() { send_stats "모델 변경" @@ -11765,7 +11765,7 @@ PYTHON_EOF install_gum install gum - + # 껌이 존재하지 않을 경우 기존의 수동 입력 과정으로 다운그레이드됩니다. if ! command -v gum >/dev/null 2>&1 || ! gum --version >/dev/null 2>&1; then echo "---모델 관리 ---" @@ -12085,7 +12085,7 @@ PYTHON_EOF - + install_plugin() { send_stats "플러그인 관리" while true; do @@ -12143,7 +12143,7 @@ PYTHON_EOF [ -z "$plugin_id" ] && continue if [ "$plugin_action" = "1" ]; then - echo "🔍 플러그인 상태 확인 중:$plugin_id" + echo "🔍 플러그인 상태 확인:$plugin_id" local plugin_list plugin_list=$(openclaw plugins list 2>/dev/null) @@ -12777,7 +12777,7 @@ PY mkdir -p "$backup_root" local tmp_payload=$(mktemp -d) || return 1 local workspaces_json=$(openclaw_get_all_agent_workspaces) - python3 -c "import json, sys, os, shutil; + python3 -c "import json, sys, os, shutil; workspaces = json.loads(sys.argv[1]); tmp_payload = sys.argv[2] for item in workspaces: aid = item['id']; ws = item['ws'] @@ -13049,7 +13049,7 @@ if os.path.isdir(agents_root): } openclaw_backup_delete_file() { - send_stats "OpenClaw 백업 파일 삭제" + send_stats "OpenClaw 삭제 백업 파일" local backup_root backup_root_real user_input target_file target_path target_type backup_root=$(openclaw_backup_root) @@ -13572,7 +13572,7 @@ PY local ver ver=$(sqlite3 --version 2>/dev/null | awk '{print $1}') echo "✅ sqlite3 사용 가능: ${ver:-unknown}" - echo "ℹ️ sqlite 확장 지원은 안정적으로 감지될 수 없으며 계속됩니다." + echo "ℹ️ sqlite 확장 지원은 안정적으로 감지할 수 없으며 계속됩니다." return 0 } @@ -13590,7 +13590,7 @@ PY elif command -v wget >/dev/null 2>&1; then wget -qO- https://bun.sh/install | bash else - echo "❌ 컬 또는 wget이 감지되지 않아 롤빵을 설치할 수 없습니다." + echo "❌ 컬이나 wget이 감지되지 않아 롤빵을 설치할 수 없습니다." return 1 fi if [ -d "$HOME/.bun/bin" ]; then @@ -13981,7 +13981,7 @@ EOF fi else echo "includeDefaultMemory 구성이 정상입니다." - echo "실행 예정: 기존 인덱스 정리 → 모든 에이전트 인덱스 완전 재구축" + echo "실행 예정: 기존 인덱스 정리 → 모든 에이전트 인덱스 완전히 재구축" echo "" read -e -p "실행을 확인하시겠습니까? (예/아니요):" confirm_fix if [[ ! "$confirm_fix" =~ ^[Nn]$ ]]; then @@ -14447,9 +14447,9 @@ PY local ask="$2" local fallback="$3" local approvals_file="$HOME/.openclaw/exec-approvals.json" - + mkdir -p "$HOME/.openclaw" - + # JSON을 생성하고 openclaw 승인 세트 --stdin을 통해 작성(선호) # CLI가 이를 지원하지 않으면 파일을 직접 작성하는 것으로 대체됩니다. local json_payload @@ -14472,7 +14472,7 @@ data["defaults"]["askFallback"] = sys.argv[4] data["defaults"]["autoAllowSkills"] = True print(json.dumps(data, indent=2)) ' "$approvals_file" "$sec" "$ask" "$fallback") - + if openclaw_has_command openclaw && echo "$json_payload" | openclaw approvals set --stdin >/dev/null 2>&1; then return 0 fi @@ -14512,7 +14512,7 @@ print(json.dumps(data, indent=2)) echo "실행 제한: ${current_sec:-(unset)}" echo "승인 프롬프트: ${current_ask:-(unset)}" echo "권한 상승 스위치: ${current_elevated:-(unset)}" - + echo -e "\n${gl_huang}[기본 Exec 승인 상태]${gl_bai}" if openclaw_has_command openclaw; then local approvals_json @@ -14563,18 +14563,18 @@ except Exception: openclaw_permission_apply_standard() { send_stats "OpenClaw 권한 - 표준 보안 모드" openclaw_permission_require_openclaw || return 1 - - echo "애플리케이션 계층 정책 구성 중..." + + echo "애플리케이션 레이어 정책 구성 중..." openclaw config set tools.profile coding >/dev/null 2>&1 openclaw config set tools.exec.security allowlist >/dev/null 2>&1 openclaw config set tools.exec.ask on-miss >/dev/null 2>&1 openclaw config set tools.elevated.enabled false >/dev/null 2>&1 openclaw config set tools.exec.strictInlineEval true >/dev/null 2>&1 # 拦截危险的内联代码 openclaw config unset commands.bash >/dev/null 2>&1 # 废弃旧版参数 - + echo "호스트 승인 차단 구성 중..." openclaw_permission_update_exec_approvals "allowlist" "on-miss" "deny" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ 표준 안전 모드로 전환(위험한 명령은 모두 UI/TG를 통해 승인을 요청합니다)${gl_bai}" } @@ -14582,36 +14582,36 @@ except Exception: openclaw_permission_apply_developer() { send_stats "OpenClaw 권한 - 개발 강화 모드" openclaw_permission_require_openclaw || return 1 - - echo "애플리케이션 계층 정책 구성 중..." + + echo "애플리케이션 레이어 정책 구성 중..." openclaw config set tools.profile coding >/dev/null 2>&1 openclaw config set tools.exec.security allowlist >/dev/null 2>&1 openclaw config set tools.exec.ask on-miss >/dev/null 2>&1 openclaw config set tools.elevated.enabled true >/dev/null 2>&1 # 允许智能体申请提权 openclaw config set tools.exec.strictInlineEval false >/dev/null 2>&1 - + echo "호스트 승인 차단 구성 중..." openclaw_permission_update_exec_approvals "allowlist" "on-miss" "deny" - + openclaw_permission_restart_gateway - echo -e "${gl_lv}✅ 개발 강화 모드로 전환(권한 상승은 허용되지만, 일반적으로 위험한 명령은 여전히 ​​승인이 필요함)${gl_bai}" + echo -e "${gl_lv}✅ 개발 강화 모드로 전환(권한 상승은 허용되지만 일반적인 위험한 명령에는 여전히 승인이 필요함)${gl_bai}" } openclaw_permission_apply_full() { send_stats "OpenClaw 권한 - 완전 개방 모드" openclaw_permission_require_openclaw || return 1 - - echo "애플리케이션 계층 정책 구성 중..." + + echo "애플리케이션 레이어 정책 구성 중..." openclaw config set tools.profile full >/dev/null 2>&1 openclaw config set tools.exec.security full >/dev/null 2>&1 openclaw config set tools.exec.ask off >/dev/null 2>&1 openclaw config set tools.elevated.enabled true >/dev/null 2>&1 openclaw config set tools.exec.strictInlineEval false >/dev/null 2>&1 - + echo "호스트 차단 방어 붕괴…" # 여기서 전체 및 해제는 기본 호스트의 실행 승인 시스템을 완전히 우회합니다. openclaw_permission_update_exec_approvals "full" "off" "full" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ 완전 개방 모드로 전환되었습니다. (경고: 모든 호스트 명령 차단이 만료되었으며 에이전트는 가장 높은 권한을 가집니다.)${gl_bai}" } @@ -14619,14 +14619,14 @@ except Exception: openclaw_permission_restore_official_defaults() { send_stats "OpenClaw 권한-공식 기본값 복원" openclaw_permission_require_openclaw || return 1 - + echo "깨끗한 애플리케이션 레이어 힘 범위..." openclaw config unset tools.profile >/dev/null 2>&1 openclaw config unset tools.exec.security >/dev/null 2>&1 openclaw config unset tools.exec.ask >/dev/null 2>&1 openclaw config unset tools.elevated.enabled >/dev/null 2>&1 openclaw config unset tools.exec.strictInlineEval >/dev/null 2>&1 - + echo "호스트 차단 구성을 정리합니다..." # CLI를 통해 승인 구성을 지우는 데 우선순위를 두고 파일을 직접 삭제하는 방법으로 대체합니다. if echo '{"version":1,"defaults":{}}' | openclaw approvals set --stdin >/dev/null 2>&1; then @@ -14634,7 +14634,7 @@ except Exception: else rm -f "$HOME/.openclaw/exec-approvals.json" fi - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ OpenClaw 공식 보안 샌드박스 방어 메커니즘으로 복귀${gl_bai}" } @@ -15513,7 +15513,7 @@ while true; do echo -e "${gl_kjlan}1. ${color1}파고다 패널 공식 버전${gl_kjlan}2. ${color2}aaPanel Pagoda 국제 버전" echo -e "${gl_kjlan}3. ${color3}1패널 차세대 관리 패널${gl_kjlan}4. ${color4}NginxProxyManager 시각화 패널" - echo -e "${gl_kjlan}5. ${color5}OpenList 다중 저장소 파일 목록 프로그램${gl_kjlan}6. ${color6}Ubuntu 원격 데스크톱 웹 버전" + echo -e "${gl_kjlan}5. ${color5}OpenList 다중 저장소 파일 목록 프로그램${gl_kjlan}6. ${color6}Ubuntu 원격 데스크톱 웹 에디션" echo -e "${gl_kjlan}7. ${color7}나타 프로브 VPS 모니터링 패널${gl_kjlan}8. ${color8}QB 오프라인 BT 자기 다운로드 패널" echo -e "${gl_kjlan}9. ${color9}Poste.io 메일 서버 프로그램${gl_kjlan}10. ${color10}RocketChat 다자간 온라인 채팅 시스템" echo -e "${gl_kjlan}-------------------------" @@ -15579,6 +15579,7 @@ while true; do echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}111. ${color111}다중 형식 파일 변환 도구${gl_kjlan}112. ${color112}행운의 대형 인트라넷 침투 도구" echo -e "${gl_kjlan}113. ${color113}파이어폭스 브라우저${gl_kjlan}114. ${color114}OpenClaw 봇 관리 도구${gl_huang}★${gl_bai}" + echo -e "${gl_kjlan}115. ${color115}헤르메스 로봇 관리 도구${gl_huang}★${gl_bai}" echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}타사 애플리케이션 목록" echo -e "${gl_kjlan}귀하의 앱이 여기에 표시되기를 원하십니까? 개발자 가이드를 확인하세요:${gl_huang}https://dev.kejilion.sh/${gl_bai}" @@ -15783,7 +15784,7 @@ while true; do } - local docker_describe="webtop은 Ubuntu 기반 컨테이너입니다. 해당 IP에 접속할 수 없는 경우, 접속할 도메인 이름을 추가해 주세요." + local docker_describe="webtop은 Ubuntu 기반 컨테이너입니다. 해당 IP에 접근할 수 없는 경우, 접근할 도메인 이름을 추가해주세요." local docker_url="공식 홈페이지 소개: https://docs.linuxserver.io/images/docker-webtop/" local docker_use="" local docker_passwd="" @@ -15915,7 +15916,7 @@ while true; do 1) setup_docker_dir check_disk_space 2 /home/docker - read -e -p "이메일 도메인 이름을 설정하세요(예: mail.yuming.com):" yuming + read -e -p "이메일 도메인 이름을 설정하십시오(예: mail.yuming.com):" yuming mkdir -p /home/docker echo "$yuming" > /home/docker/mail.txt echo "------------------------" @@ -16483,7 +16484,7 @@ while true; do } - local docker_describe="웹탑은 중국어 버전의 Alpine 컨테이너를 기반으로 합니다. 해당 IP에 접속할 수 없는 경우, 접속할 도메인 이름을 추가해 주세요." + local docker_describe="웹탑은 중국어 버전의 Alpine 컨테이너를 기반으로 합니다. 해당 IP에 접근할 수 없는 경우, 접근할 도메인 이름을 추가해주세요." local docker_url="공식 홈페이지 소개: https://docs.linuxserver.io/images/docker-webtop/" local docker_use="" local docker_passwd="" @@ -16649,7 +16650,7 @@ while true; do frooodle/s-pdf:latest } - local docker_describe="이는 분할 병합, 변환, 재구성, 이미지 추가, 회전, 압축 등과 같은 PDF 파일에 대한 다양한 작업을 수행할 수 있는 Docker를 사용하여 로컬로 호스팅되는 강력한 웹 기반 PDF 조작 도구입니다." + local docker_describe="이는 분할 병합, 변환, 재구성, 이미지 추가, 회전, 압축 등과 같은 PDF 파일에 대한 다양한 작업을 수행할 수 있는 docker를 사용하는 강력한 로컬 호스팅 웹 기반 PDF 조작 도구입니다." local docker_url="공식 웹사이트 소개:${gh_proxy}github.com/Stirling-Tools/Stirling-PDF" local docker_use="" local docker_passwd="" @@ -17154,7 +17155,7 @@ while true; do } - local docker_describe="OpenWebUI는 새로운 llama3 대규모 언어 모델에 연결된 대규모 언어 모델 웹 페이지 프레임워크입니다." + local docker_describe="OpenWebUI는 새로운 llama3 대규모 언어 모델에 연결되는 대규모 언어 모델 웹 페이지 프레임워크입니다." local docker_url="공식 웹사이트 소개:${gh_https_url}github.com/open-webui/open-webui" local docker_use="docker exec ollama ollama run llama3.2:1b" local docker_passwd="" @@ -17316,7 +17317,7 @@ while true; do local app_id="60" local app_name="JumpServer 오픈 소스 요새 머신" - local app_text="오픈소스 권한 있는 액세스 관리(PAM) 도구입니다. 이 프로그램은 포트 80을 사용하며 액세스를 위한 도메인 이름 추가를 지원하지 않습니다." + local app_text="오픈소스 PAM(Privileged Access Management) 도구입니다. 이 프로그램은 포트 80을 사용하며 액세스를 위한 도메인 이름 추가를 지원하지 않습니다." local app_url="공식 소개:${gh_https_url}github.com/jumpserver/jumpserver" local docker_name="jms_web" local docker_port="80" @@ -17897,7 +17898,7 @@ while true; do local app_id="80" local app_name="링크워든 북마크 관리" - local app_text="태그 지정, 검색 및 팀 협업을 지원하는 오픈 소스, 자체 호스팅 북마크 관리 플랫폼입니다." + local app_text="태그 지정, 검색 및 팀 협업을 지원하는 오픈 소스 자체 호스팅 북마크 관리 플랫폼입니다." local app_url="공식 홈페이지: https://linkwarden.app/" local docker_name="linkwarden-linkwarden-1" local docker_port="8080" @@ -18206,7 +18207,7 @@ while true; do } - local docker_describe="원격으로 영화와 생방송을 함께 시청할 수 있는 프로그램입니다. 동시 시청, 라이브 방송, 채팅 및 기타 기능을 제공합니다." + local docker_describe="영화와 생방송을 원격으로 함께 시청할 수 있는 프로그램입니다. 동시 시청, 라이브 방송, 채팅 및 기타 기능을 제공합니다." local docker_url="공식 웹사이트 소개:${gh_https_url}github.com/synctv-org/synctv" local docker_use="echo \"초기 계정 및 비밀번호: root. 로그인 후 시간에 맞춰 로그인 비밀번호를 변경하세요\"" local docker_passwd="" @@ -18265,7 +18266,7 @@ while true; do } - local docker_describe="익명의 비밀번호로 텍스트와 파일을 공유하고, 빠른 배송과 같은 파일 픽업" + local docker_describe="익명의 비밀번호로 텍스트와 파일을 공유하고 빠른 배송과 같은 파일 픽업" local docker_url="공식 웹사이트 소개:${gh_https_url}github.com/vastsa/FileCodeBox" local docker_use="echo \"접속 주소 뒤에는 /#/admin이 붙어서 관리자 페이지에 접속합니다\"" local docker_passwd="echo \"관리자 비밀번호: FileCodeBox2023\"" @@ -19246,6 +19247,9 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ moltbot_menu ;; + 115|hermes) + bash <(curl -sL ${gh_proxy}raw.githubusercontent.com/kejilion/sh/main/hermes_manager.sh) + ;; b) clear @@ -19287,7 +19291,7 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ r) root_use send_stats "모든 앱 복원" - echo "사용 가능한 애플리케이션 백업" + echo "사용 가능한 앱 백업" echo "-------------------------" ls -lt /app*.gz | awk '{print $NF}' echo "" @@ -20035,7 +20039,7 @@ linux_Settings() { echo -e "${gl_kjlan}3. ${gl_bai}사용자 비밀번호 로그인 모드${gl_kjlan}4. ${gl_bai}지정된 버전의 Python 설치" echo -e "${gl_kjlan}5. ${gl_bai}모든 포트 열기${gl_kjlan}6. ${gl_bai}SSH 연결 포트 수정" echo -e "${gl_kjlan}7. ${gl_bai}DNS 주소 최적화${gl_kjlan}8. ${gl_bai}한 번의 클릭으로 시스템을 다시 설치${gl_huang}★${gl_bai}" - echo -e "${gl_kjlan}9. ${gl_bai}ROOT 계정을 비활성화하고 새 계정을 만듭니다.${gl_kjlan}10. ${gl_bai}우선순위 ipv4/ipv6 전환" + echo -e "${gl_kjlan}9. ${gl_bai}ROOT 계정을 비활성화하고 새 계정을 만듭니다.${gl_kjlan}10. ${gl_bai}우선 순위 ipv4/ipv6 전환" echo -e "${gl_kjlan}------------------------" echo -e "${gl_kjlan}11. ${gl_bai}항만점유현황 확인${gl_kjlan}12. ${gl_bai}가상 메모리 크기 수정" echo -e "${gl_kjlan}13. ${gl_bai}사용자 관리${gl_kjlan}14. ${gl_bai}사용자/비밀번호 생성기" @@ -20045,7 +20049,7 @@ linux_Settings() { echo -e "${gl_kjlan}------------------------" echo -e "${gl_kjlan}21. ${gl_bai}기본 호스트 확인${gl_kjlan}22. ${gl_bai}SSH 방어 프로그램" echo -e "${gl_kjlan}23. ${gl_bai}전류 제한 자동 종료${gl_kjlan}24. ${gl_bai}사용자 키 로그인 모드" - echo -e "${gl_kjlan}25. ${gl_bai}TG-bot 시스템 모니터링 및 조기 경보${gl_kjlan}26. ${gl_bai}OpenSSH 고위험 취약점 수정" + echo -e "${gl_kjlan}25. ${gl_bai}TG-bot 시스템 모니터링 및 조기경보${gl_kjlan}26. ${gl_bai}OpenSSH 고위험 취약점 수정" echo -e "${gl_kjlan}27. ${gl_bai}Red Hat Linux 커널 업그레이드${gl_kjlan}28. ${gl_bai}Linux 시스템 커널 매개변수 최적화${gl_huang}★${gl_bai}" echo -e "${gl_kjlan}29. ${gl_bai}바이러스 검사 도구${gl_huang}★${gl_bai} ${gl_kjlan}30. ${gl_bai}파일 관리자" echo -e "${gl_kjlan}------------------------" @@ -20333,7 +20337,7 @@ EOF case "$choice" in 1) - send_stats "1G 가상 메모리가 설정되었습니다" + send_stats "1G 가상 메모리가 설정되었습니다." add_swap 1024 ;; @@ -20780,7 +20784,7 @@ EOF echo -e "${gl_lv}현재 설정된 인바운드 트래픽 제한 임계값은 다음과 같습니다.${gl_huang}${rx_threshold_gb}${gl_lv}G${gl_bai}" echo -e "${gl_lv}현재 설정된 아웃바운드 트래픽 제한 임계값은 다음과 같습니다.${gl_huang}${tx_threshold_gb}${gl_lv}GB${gl_bai}" else - echo -e "${gl_hui}현재 제한 종료 기능이 현재 활성화되어 있지 않습니다.${gl_bai}" + echo -e "${gl_hui}현재 제한 종료 기능이 활성화되어 있지 않습니다.${gl_bai}" fi echo @@ -20796,7 +20800,7 @@ EOF case "$Limiting" in 1) # 새 가상 메모리 크기 입력 - echo "실제 서버의 트래픽이 100G만 있는 경우 임계값을 95G로 설정하고 미리 종료하여 트래픽 오류나 오버플로를 방지할 수 있습니다." + echo "실제 서버에 트래픽이 100G만 있는 경우 임계값을 95G로 설정하고 미리 종료하여 트래픽 오류나 오버플로를 방지할 수 있습니다." read -e -p "인바운드 트래픽 임계값을 입력하십시오(단위는 G, 기본값은 100G)." rx_threshold_gb rx_threshold_gb=${rx_threshold_gb:-100} read -e -p "아웃바운드 트래픽 임계값을 입력하십시오(단위는 G, 기본값은 100G)." tx_threshold_gb @@ -21398,7 +21402,7 @@ run_commands_on_servers() { local username=${SERVER_ARRAY[i+3]} local password=${SERVER_ARRAY[i+4]} echo - echo -e "${gl_huang}연결 대상$name ($hostname)...${gl_bai}" + echo -e "${gl_huang}연결하다$name ($hostname)...${gl_bai}" # sshpass -p "$password" ssh -o StrictHostKeyChecking=no "$username@$hostname" -p "$port" "$1" sshpass -p "$password" ssh -t -o StrictHostKeyChecking=no "$username@$hostname" -p "$port" "$1" done @@ -21473,7 +21477,7 @@ while true; do 5) clear send_stats "클러스터 복원" - echo "server.py를 업로드하고 아무 키나 눌러 업로드를 시작하세요!" + echo "귀하의 server.py를 업로드하고 업로드를 시작하려면 아무 키나 누르십시오!" echo -e "업로드해주세요${gl_huang}servers.py${gl_bai}파일을 제출하다${gl_huang}/root/cluster/${gl_bai}복원 완료!" break_end ;; @@ -21706,7 +21710,7 @@ while true; do if [ -f ~/kejilion.sh.bak ]; then mv -f ~/kejilion.sh.bak ~/kejilion.sh fi - echo -e "${gl_hong}업데이트 실패! 다운로드 중 오류가 발생했거나 파일 확인에 실패했습니다. 원본 버전이 복원되었습니다.${gl_bai}" + echo -e "${gl_hong}업데이트에 실패했습니다! 다운로드 중 오류가 발생했거나 파일 확인에 실패했습니다. 원본 버전이 복원되었습니다.${gl_bai}" send_stats "스크립트 업데이트 실패" fi break_end @@ -21830,7 +21834,7 @@ done k_info() { -send_stats "k 명령 참조 예" +send_stats "k 명령 참조 사용 사례" echo "-------------------" echo "영상 소개: https://www.bilibili.com/video/BV1ib421E7it?t=0.1" echo "다음은 k 명령의 참조 사용 사례입니다." @@ -21874,7 +21878,7 @@ echo "k 포트 닫기 gbdk 7800 |k 포트 7800 닫기" echo "릴리스 IP k fxip 127.0.0.0/8 |k 릴리스 IP 127.0.0.0/8" echo "IP 차단 k zzip 177.5.25.36 |k IP 177.5.25.36 차단" echo "명령 즐겨찾기 k 즐겨찾기 | k 명령 즐겨찾기" -echo "애플리케이션 시장 관리 k app" +echo "애플리케이션 시장관리 kapp" echo "신청번호의 빠른 관리 k app 26 | k 앱 1패널 | k 앱 npm" echo "Fail2ban 관리 k Fail2ban | 케이 F2B" echo "시스템 정보 표시 k 정보" diff --git a/tw/kejilion.sh b/tw/kejilion.sh index d196239ed..89d9700b8 100644 --- a/tw/kejilion.sh +++ b/tw/kejilion.sh @@ -1,5 +1,5 @@ #!/bin/bash -sh_v="4.4.9" +sh_v="4.4.10" gl_hui='\e[37m' @@ -497,7 +497,7 @@ while true; do echo "------------------------" echo "15. 開啟容器連接埠存取 16. 關閉容器連接埠訪問" echo "------------------------" - echo "0. 返回上一級選單" + echo "0. 返回上一级选单" echo "------------------------" read -e -p "請輸入你的選擇:" sub_choice case $sub_choice in @@ -589,7 +589,7 @@ while true; do ;; 15) - send_stats "允許容器連接埠訪問" + send_stats "允许容器端口访问" read -e -p "請輸入容器名稱:" docker_name ip_address clear_container_rules "$docker_name" "$ipv4_address" @@ -634,7 +634,7 @@ while true; do case $sub_choice in 1) send_stats "拉取鏡像" - read -e -p "請輸入鏡像名稱(多個鏡像名稱請以空格分隔):" imagenames + read -e -p "请输入镜像名(多个镜像名请用空格分隔): " imagenames for name in $imagenames; do echo -e "${gl_kjlan}正在取得鏡像:$name${gl_bai}" docker pull $name @@ -1206,7 +1206,7 @@ iptables_panel() { ;; 17) - read -e -p "請輸入清除的國家代碼(多個國家代碼可用空格隔開如 CN US JP):" country_code + read -e -p "请输入清除的国家代码(多个国家代码可用空格隔开如 CN US JP): " country_code manage_country_rules unblock $country_code send_stats "清除國家$country_code的IP" ;; @@ -1498,7 +1498,7 @@ ssl_ps ssl_ps() { echo -e "${gl_huang}已申請的證書到期情況${gl_bai}" - echo "網站資訊 證書到期時間" + echo "站點資訊 證書到期時間" echo "------------------------" for cert_dir in /etc/letsencrypt/live/*; do local cert_file="$cert_dir/fullchain.pem" @@ -1561,15 +1561,15 @@ certs_status() { ;; 2) - send_stats "导入已有证书" + send_stats "導入已有證書" - # 定义文件路径 + # 定義檔案路徑 local cert_file="/home/web/certs/${yuming}_cert.pem" local key_file="/home/web/certs/${yuming}_key.pem" mkdir -p /home/web/certs - # 1. 輸入憑證 (ECC 和 RSA 憑證開頭都是 BEGIN CERTIFICATE) + # 1. 输入证书 (ECC 和 RSA 证书开头都是 BEGIN CERTIFICATE) echo "請貼上 證書 (CRT/PEM) 內容 (以兩次回車結束):" local cert_content="" while IFS= read -r line; do @@ -1627,7 +1627,7 @@ fi add_yuming() { ip_address echo -e "先將網域名稱解析到本機IP:${gl_huang}$ipv4_address $ipv6_address${gl_bai}" - read -e -p "請輸入你的IP或解析過的網域名稱:" yuming + read -e -p "请输入你的IP或者解析过的域名: " yuming } @@ -1829,7 +1829,7 @@ nginx_waf() { sed -i 's|^\(\s*\)# modsecurity on;|\1modsecurity on;|' /home/web/nginx.conf > /dev/null 2>&1 sed -i 's|^\(\s*\)# modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;|\1modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;|' /home/web/nginx.conf > /dev/null 2>&1 elif [ "$mode" == "off" ]; then - # 關閉 WAF:加上註釋 + # 关闭 WAF:加上注释 sed -i 's|^load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;|# load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;|' /home/web/nginx.conf > /dev/null 2>&1 sed -i 's|^\(\s*\)modsecurity on;|\1# modsecurity on;|' /home/web/nginx.conf > /dev/null 2>&1 sed -i 's|^\(\s*\)modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;|\1# modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;|' /home/web/nginx.conf > /dev/null 2>&1 @@ -2566,7 +2566,7 @@ check_docker_image_update() { local remote_date=$(curl -s "$api_url" | jq -r '.published_at' 2>/dev/null) elif [[ "$full_image_name" == *"oneimg"* ]]; then - # --- 場景 B: 特殊指定 (即便在 Docker Hub,也想透過 GitHub Release 判斷) --- + # --- 场景 B: 特殊指定 (即便在 Docker Hub,也想通过 GitHub Release 判断) --- local api_url="https://api.github.com/repos/onexru/oneimg/releases/latest" local remote_date=$(curl -s "$api_url" | jq -r '.published_at' 2>/dev/null) @@ -2789,7 +2789,7 @@ clear_host_port_rules() { install iptables - # 清除封禁所有其他 IP 访问的规则 + # 清除封鎖所有其他 IP 存取的規則 if iptables -C INPUT -p tcp --dport "$port" -j DROP &>/dev/null; then iptables -D INPUT -p tcp --dport "$port" -j DROP fi @@ -3005,7 +3005,7 @@ docker_app_plus() { echo "1. 安裝 2. 更新 3. 卸載" echo "------------------------" echo "5. 新增網域存取 6. 刪除網域存取" - echo "7. 允許IP+連接埠存取 8. 阻止IP+連接埠訪問" + echo "7. 允许IP+端口访问 8. 阻止IP+端口访问" echo "------------------------" echo "0. 返回上一級選單" echo "------------------------" @@ -3241,7 +3241,7 @@ f2b_basic_config() { fi echo "即將配置 SSH jail:$jail_name" - read -e -p "封禁時長 bantime (秒/分鐘/小時,如 3600 或 1h) [預設 1h]:" bantime + read -e -p "封禁时长 bantime (秒/分钟/小时,如 3600 或 1h) [默认 1h]: " bantime read -e -p "時間窗口 findtime (秒/分鐘/小時,如 600 或 10m) [預設 10m]:" findtime read -e -p "重試次數 maxretry (整數) [預設 5]:" maxretry @@ -3268,13 +3268,13 @@ EOF fi fi - echo -e "${gl_lv}已寫入配置${gl_bai}: /etc/fail2ban/jail.d/sshd.local" + echo -e "${gl_lv}已写入配置${gl_bai}: /etc/fail2ban/jail.d/sshd.local" fail2ban-client reload >/dev/null 2>&1 || true sleep 2 fail2ban-client status $jail_name || true } -# 直接打开主配置/覆盖配置编辑(nano) +# 直接開啟主配置/覆蓋配置編輯(nano) # 優先編輯 /etc/fail2ban/jail.d/sshd.local(更安全),若不存在則創建 f2b_edit_config() { root_use @@ -3387,7 +3387,7 @@ nginx_upgrade clear local nginx_version=$(docker exec nginx nginx -v 2>&1) local nginx_version=$(echo "$nginx_version" | grep -oP "nginx/\K[0-9]+\.[0-9]+\.[0-9]+") -echo "nginx已安裝完成" +echo "nginx已安装完成" echo -e "目前版本:${gl_huang}v$nginx_version${gl_bai}" echo "" @@ -3879,7 +3879,7 @@ ldnmp_web_status() { case $sub_choice in 1) send_stats "申請網域證書" - read -e -p "请输入你的域名: " yuming + read -e -p "請輸入你的網域名稱:" yuming install_certbot docker run --rm -v /etc/letsencrypt/:/etc/letsencrypt certbot/certbot delete --cert-name "$yuming" -n 2>/dev/null install_ssltls @@ -3890,7 +3890,7 @@ ldnmp_web_status() { 2) send_stats "克隆站點域名" read -e -p "請輸入舊網域名稱:" oddyuming - read -e -p "請輸入新網域名稱:" yuming + read -e -p "請輸入新網域:" yuming install_certbot install_ssltls certs_status @@ -3930,8 +3930,8 @@ ldnmp_web_status() { 4) send_stats "建立關聯站點" echo -e "為現有的站點再關聯一個新網域用於訪問" - read -e -p "請輸入現有的網域名稱:" oddyuming - read -e -p "請輸入新網域名稱:" yuming + read -e -p "请输入现有的域名: " oddyuming + read -e -p "請輸入新網域:" yuming install_certbot install_ssltls certs_status @@ -4085,7 +4085,7 @@ donlond_frp() { generate_frps_config() { send_stats "安裝frp服務端" - # 產生隨機連接埠和憑證 + # 生成随机端口和凭证 local bind_port=8055 local dashboard_port=8056 local token=$(openssl rand -hex 16) @@ -4128,7 +4128,7 @@ EOF configure_frpc() { send_stats "安裝frp客戶端" read -e -p "請輸入外網對接IP:" server_addr - read -e -p "請輸入外網對接token:" token + read -e -p "请输入外网对接token: " token echo mkdir -p /home/frp @@ -4148,7 +4148,7 @@ EOF } add_forwarding_service() { - send_stats "新增frp內網服務" + send_stats "添加frp内网服务" # 提示使用者輸入服務名稱和轉發訊息 read -e -p "請輸入服務名稱:" service_name read -e -p "請輸入轉送類型 (tcp/udp) [回​​車預設tcp]:" service_type @@ -4779,7 +4779,7 @@ linux_clean() { bbr_on() { -# 统一写入到 sysctl.d 以防与内核调优模块打架 +# 統一寫入到 sysctl.d 以防與核心調優模組打架 local CONF="/etc/sysctl.d/99-kejilion-bbr.conf" mkdir -p /etc/sysctl.d echo "net.core.default_qdisc=fq" > "$CONF" @@ -5135,7 +5135,7 @@ sshkey_panel() { echo -e "使用者密鑰登入模式${IS_KEY_ENABLED}" echo "進階玩法: https://blog.kejilion.pro/ssh-key" echo "------------------------------------------------" - echo "將會產生金鑰對,更安全的方式SSH登錄" + echo "将会生成密钥对,更安全的方式SSH登录" echo "------------------------" echo "1. 產生新密鑰對 2. 手動輸入已有公鑰" echo "3. 从GitHub导入已有公钥 4. 从URL导入已有公钥" @@ -5938,7 +5938,7 @@ clamav() { # ============================================================================ # Linux 核心調優模組(重構版) -# 統一核心函數 + 場景差異化參數 + 持久化到設定檔 + 硬體自適應 +# 统一核心函数 + 场景差异化参数 + 持久化到配置文件 + 硬件自适应 # 取代原 optimize_high_performance / optimize_balanced / optimize_web_server / restore_defaults # ============================================================================ @@ -6112,7 +6112,7 @@ net.ipv4.tcp_slow_start_after_idle = 0" # 模式: $mode_name | 場景: $scene # 記憶體: ${MEM_MB}MB | 產生時間: $(date '+%Y-%m-%d %H:%M:%S') -# ── TCP 擁塞控制 ── +# ── TCP 拥塞控制 ── net.core.default_qdisc = $QDISC net.ipv4.tcp_congestion_control = $CC @@ -6227,7 +6227,7 @@ LIMITS # ── BBR 持久化 ── if [ "$CC" = "bbr" ]; then echo "tcp_bbr" > /etc/modules-load.d/bbr.conf 2>/dev/null - # 清理舊的 sysctl.conf 裡的 bbr 設定(避免衝突) + # 清理旧的 sysctl.conf 里的 bbr 配置(避免冲突) sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf 2>/dev/null fi @@ -6303,7 +6303,7 @@ Kernel_optimize() { echo -e "2. 均衡最佳化模式: 在效能與資源消耗之間取得平衡,適合日常使用。" echo -e "3. 網站最佳化模式: 針對網站伺服器最佳化,超高並發連線佇列。" echo -e "4. 直播最佳化模式: 針對直播推流優化,UDP 緩衝區加大,減少延遲。" - echo -e "5. 游戏服优化模式: 针对游戏服务器优化,低延迟优先。" + echo -e "5. 遊戲服最佳化模式: 針對遊戲伺服器最佳化,低延遲優先。" echo -e "6. 還原預設設定: 將系統設定還原為預設配置。" echo -e "7. 自動調優: 依測試資料自動調優核心參數。${gl_huang}★${gl_bai}" echo "--------------------" @@ -6457,7 +6457,7 @@ else echo "${bianse}" >> ~/.profile # source ~/.profile fi -echo -e "${gl_lv}變更完成。重新连接SSH后可查看变化!${gl_bai}" +echo -e "${gl_lv}變更完成。重新連接SSH後可查看變化!${gl_bai}" hash -r break_end @@ -6548,7 +6548,7 @@ linux_trash() { echo "------------------------------------------------" ls -l --color=auto "$TRASH_DIR" 2>/dev/null || echo "回收站為空" echo "------------------------" - echo "1. 啟用回收站 2. 關閉回收站" + echo "1. 启用回收站 2. 关闭回收站" echo "3. 還原內容 4. 清空回收站" echo "------------------------" echo "0. 返回上一級選單" @@ -6610,7 +6610,7 @@ create_backup() { echo "- 備份單一目錄: /var/www" echo "- 備份多個目錄: /etc /home /var/log" echo "- 直接回車將使用預設目錄 (/etc /usr /home)" - read -e -p "请输入要备份的目录(多个目录用空格分隔,直接回车则使用默认目录):" input + read -e -p "請輸入要備份的目錄(多個目錄以空格分隔,直接回車則使用預設目錄):" input # 如果使用者沒有輸入目錄,則使用預設目錄 if [ -z "$input" ]; then @@ -6638,8 +6638,8 @@ create_backup() { # 產生備份檔名 local BACKUP_NAME="${PREFIX}_$TIMESTAMP.tar.gz" - # 列印使用者選擇的目錄 - echo "您選擇的備份目錄為:" + # 打印用户选择的目录 + echo "您选择的备份目录为:" for path in "${BACKUP_PATHS[@]}"; do echo "- $path" done @@ -6705,7 +6705,7 @@ delete_backup() { if [ $? -eq 0 ]; then echo "備份刪除成功!" else - echo "备份删除失败!" + echo "備份刪除失敗!" exit 1 fi } @@ -6862,7 +6862,7 @@ kj_ssh_read_auth() { done if [[ "$password_or_key" != *"-----BEGIN"* || "$password_or_key" != *"PRIVATE KEY-----"* ]]; then - echo "無效的密鑰內容!" + echo "无效的密钥内容!" return 1 fi @@ -6981,7 +6981,7 @@ use_connection() { else # 使用密碼連接 if ! command -v sshpass &> /dev/null; then - echo "错误:未安装 sshpass,请先安装 sshpass。" + echo "錯誤:未安裝 sshpass,請先安裝 sshpass。" echo "安裝方法:" echo " - Ubuntu/Debian: apt install sshpass" echo " - CentOS/RHEL: yum install sshpass" @@ -7101,7 +7101,7 @@ mount_partition() { # 檢查 /etc/fstab 是否已經存在 UUID 或掛載點 if grep -qE "UUID=$UUID|[[:space:]]$MOUNT_POINT[[:space:]]" /etc/fstab; then - echo "/etc/fstab 中已存在该分区记录,跳过写入" + echo "/etc/fstab 中已存在該分區記錄,跳過寫入" return 0 fi @@ -7131,7 +7131,7 @@ unmount_partition() { echo "分割區卸載成功:$MOUNT_POINT" rmdir "$MOUNT_POINT" else - echo "分区卸载失败!" + echo "分區卸載失敗!" fi } @@ -7174,7 +7174,7 @@ format_partition() { *) echo "無效的選擇!"; return ;; esac - # 确认格式化 + # 確認格式化 read -e -p "確認格式化分割區 /dev/$PARTITION為$FS_TYPE嗎? (y/n):" CONFIRM if [ "$CONFIRM" != "y" ]; then echo "操作已取消。" @@ -7553,7 +7553,7 @@ linux_info() { local swap_info=$(free -m | awk 'NR==3{used=$3; total=$2; if (total == 0) {percentage=0} else {percentage=used*100/total}; printf "%dM/%dM (%d%%)", used, total, percentage}') - local runtime=$(cat /proc/uptime | awk -F. '{run_days=int($1 / 86400);run_hours=int(($1 % 86400) / 3600);run_minutes=int(($1% 3600) / 60); if (run_days > 0) printf("%d天 ", run_days); if (run_hours > 0) printf("%d時 ", run_hours); printf("%d分\n", run_minutes)}') + local runtime=$(cat /proc/uptime | awk -F. '{run_days=int($1 / 86400);run_hours=int(($1 % 86400) / 3600);run_minutes=int(($1 % 3600) / 60); if (run_days > 0) printf("%d天 ", run_days); if (run_hours > 0) printf("%d时 ", run_hours); printf("%d分\n", run_minutes)}') local timezone=$(current_timezone) @@ -7567,9 +7567,9 @@ linux_info() { echo -e "${gl_kjlan}系統版本:${gl_bai}$os_info" echo -e "${gl_kjlan}Linux版本:${gl_bai}$kernel_version" echo -e "${gl_kjlan}-------------" - echo -e "${gl_kjlan}CPU架構:${gl_bai}$cpu_arch" + echo -e "${gl_kjlan}CPU架构: ${gl_bai}$cpu_arch" echo -e "${gl_kjlan}CPU型號:${gl_bai}$cpu_info" - echo -e "${gl_kjlan}CPU核心數:${gl_bai}$cpu_cores" + echo -e "${gl_kjlan}CPU核心数: ${gl_bai}$cpu_cores" echo -e "${gl_kjlan}CPU頻率:${gl_bai}$cpu_freq" echo -e "${gl_kjlan}-------------" echo -e "${gl_kjlan}CPU佔用:${gl_bai}$cpu_usage_percent%" @@ -7586,7 +7586,7 @@ linux_info() { echo -e "${gl_kjlan}-------------" echo -e "${gl_kjlan}運營商:${gl_bai}$isp_info" if [ -n "$ipv4_address" ]; then - echo -e "${gl_kjlan}IPv4位址:${gl_bai}$ipv4_address" + echo -e "${gl_kjlan}IPv4地址: ${gl_bai}$ipv4_address" fi if [ -n "$ipv6_address" ]; then @@ -7635,7 +7635,7 @@ linux_tools() { elif command -v pkg >/dev/null 2>&1; then PM="pkg" else - echo "❌ 未識別的套件管理器" + echo "❌ 未识别的包管理器" exit 1 fi @@ -8040,10 +8040,10 @@ docker_ssh_migration() { local project_name=$(docker inspect "$c" | jq -r '.[0].Config.Labels["com.docker.compose.project"] // empty') if [ -z "$project_dir" ]; then - read -e -p "未偵測到 compose 目錄,請手動輸入路徑:" project_dir + read -e -p "未检测到 compose 目录,请手动输入路径: " project_dir fi - # 如果該 Compose 項目已經打包過,跳過 + # 如果该 Compose 项目已经打包过,跳过 if [[ -n "${PACKED_COMPOSE_PATHS[$project_dir]}" ]]; then echo -e "${gl_huang}Compose 項目 [$project_name] 已備份過,跳過重複打包...${gl_bai}" continue @@ -8113,8 +8113,8 @@ docker_ssh_migration() { restore_docker() { send_stats "Docker還原" - read -e -p "请输入要还原的备份目录: " BACKUP_DIR - [[ ! -d "$BACKUP_DIR" ]] && { echo -e "${gl_hong}备份目录不存在${gl_bai}"; return; } + read -e -p "請輸入要還原的備份目錄:" BACKUP_DIR + [[ ! -d "$BACKUP_DIR" ]] && { echo -e "${gl_hong}備份目錄不存在${gl_bai}"; return; } echo -e "${gl_kjlan}開始執行還原操作...${gl_bai}" @@ -8235,7 +8235,7 @@ docker_ssh_migration() { read -e -p "請輸入要遷移的備份目錄:" BACKUP_DIR [[ ! -d "$BACKUP_DIR" ]] && { echo -e "${gl_hong}備份目錄不存在${gl_bai}"; return; } - kj_ssh_read_host_user_port "目標伺服器IP:" "目標伺服器SSH用戶名 [預設root]:" "目標伺服器SSH連接埠 [預設22]:" "root" "22" + kj_ssh_read_host_user_port "目標伺服器IP:" "目标服务器SSH用户名 [默认root]: " "目標伺服器SSH連接埠 [預設22]:" "root" "22" local TARGET_IP="$KJ_SSH_HOST" local TARGET_USER="$KJ_SSH_USER" local TARGET_PORT="$KJ_SSH_PORT" @@ -8792,7 +8792,7 @@ linux_Oracle() { 1) clear echo "活躍腳本: CPU佔用10-20% 記憶體佔用20%" - read -e -p "确定安装吗? (Y/N):" choice + read -e -p "確定安裝嗎? (Y/N):" choice case "$choice" in [Yy]) @@ -8994,7 +8994,7 @@ linux_ldnmp() { echo -e "${gl_huang}29. ${gl_bai}Stream四層代理轉發${gl_huang}30. ${gl_bai}自訂靜態站點" echo -e "${gl_huang}------------------------" echo -e "${gl_huang}31. ${gl_bai}站點資料管理${gl_huang}★${gl_bai} ${gl_huang}32. ${gl_bai}備份全站數據" - echo -e "${gl_huang}33. ${gl_bai}定時遠端備份${gl_huang}34. ${gl_bai}還原全站數據" + echo -e "${gl_huang}33. ${gl_bai}定時遠端備份${gl_huang}34. ${gl_bai}还原全站数据" echo -e "${gl_huang}------------------------" echo -e "${gl_huang}35. ${gl_bai}防護LDNMP環境${gl_huang}36. ${gl_bai}優化LDNMP環境" echo -e "${gl_huang}37. ${gl_bai}更新LDNMP環境${gl_huang}38. ${gl_bai}解除安裝LDNMP環境" @@ -9431,7 +9431,7 @@ linux_ldnmp() { clear echo -e "[${gl_huang}6/6${gl_bai}] 資料庫管理" echo "-------------" - read -e -p "1. 我搭建新站 2. 我搭建老站有数据库备份: " use_db + read -e -p "1. 我搭建新站 2. 我搭建老站有資料庫備份:" use_db case $use_db in 1) echo @@ -9730,7 +9730,7 @@ linux_ldnmp() { clear send_stats "定時遠端備份" read -e -p "輸入遠端伺服器IP:" useip - read -e -p "輸入遠端伺服器密碼:" usepasswd + read -e -p "输入远程服务器密码: " usepasswd cd ~ wget -O ${useip}_beifen.sh ${gh_proxy}raw.githubusercontent.com/kejilion/sh/main/beifen.sh > /dev/null 2>&1 @@ -10054,7 +10054,7 @@ moltbot_menu() { echo "6. API管理" echo "7. 機器人連線對接" echo "8. 插件管理(安裝/刪除)" - echo "9. 技能管理(安裝/刪除)" + echo "9. 技能管理(安装/删除)" echo "10. 編輯主設定文件" echo "11. 配置精靈" echo "12. 健康檢測與修復" @@ -10216,7 +10216,7 @@ def collect_available_refs(exclude_provider=None): def prompt_delete_provider(name): - prompt = f"⚠️ {name} /models 偵測連續失敗 3 次。是否刪除該 API 供應商及其全部相關模型? [y/N]:" + prompt = f"⚠️ {name} /models 探测连续失败 3 次。是否删除该 API 供应商及其全部相关模型? [y/N]:" try: ans = input(prompt).strip().lower() except EOFError: @@ -10251,7 +10251,7 @@ def rebind_defaults_before_delete(name): if ref_provider(val) == name: repl = get_replacement() if not repl: - summary.append(f'❌ {name}: {fk} 指向該 provider,但無可用替代模型,已中止刪除') + summary.append(f'❌ {name}: {fk} 指向该 provider,但无可用替代模型,已中止删除') return False defaults[fk] = repl changed = True @@ -10350,7 +10350,7 @@ for name, provider in list(providers.items()): remote_set = set(remote_ids) if not remote_set: - fatal_errors.append(f'❌ {name} 上游 /models 為空,無法為該 provider 提供兜底模型') + fatal_errors.append(f'❌ {name} 上游 /models 为空,无法为该 provider 提供兜底模型') continue local_models = [m for m in model_list if isinstance(m, dict) and m.get('id')] @@ -10391,7 +10391,7 @@ for name, provider in list(providers.items()): if isinstance(primary_ref, str) and primary_ref in (local_refs - expected_refs): set_primary_ref(defaults, first_ref) changed = True - summary.append(f'🔁 默认模型已兜底替换: {primary_ref} -> {first_ref}') + summary.append(f'🔁 預設模型已兜底替換: {primary_ref} -> {first_ref}') for fk in ('modelFallback', 'imageModelFallback'): val = defaults.get(fk) @@ -10633,7 +10633,7 @@ EOF fi local model_count=$(echo "$model_ids" | wc -l) - echo "✅ 發現$model_count個模型" + echo "✅ 发现 $model_count個模型" local models_array models_array=$(build-openclaw-provider-models-json "$provider_name" "$model_ids") @@ -10684,12 +10684,12 @@ EOF # 1. Provider 名稱 read -erp "請輸入 Provider 名稱 (如: deepseek):" provider_name while [[ -z "$provider_name" ]]; do - echo "❌ Provider 名稱不能為空" + echo "❌ Provider 名称不能为空" read -erp "請輸入 Provider 名稱:" provider_name done # 2. Base URL - read -erp "請輸入 Base URL (如: https://api.xxx.com/v1):" base_url + read -erp "请输入 Base URL (如: https://api.xxx.com/v1): " base_url while [[ -z "$base_url" ]]; do echo "❌ Base URL 不能為空" read -erp "請輸入 Base URL:" base_url @@ -10771,19 +10771,19 @@ EOF if [[ $add_result -eq 0 ]]; then echo - echo "🔄 設定預設模型並重新啟動網關..." + echo "🔄 设置默认模型并重启网关..." openclaw models set "$provider_name/$default_model" openclaw_sync_sessions_model "$provider_name/$default_model" start_gateway echo "$finish_msg" - echo "✅ 當前 API 協定類型:$DETECTED_API" + echo "✅ 当前 API 协议类型: $DETECTED_API" fi break_end } - + openclaw_api_manage_list() { local config_file="${HOME}/.openclaw/openclaw.json" send_stats "OpenClaw API列表" @@ -10849,7 +10849,7 @@ try: with open(path, 'r', encoding='utf-8') as f: obj = json.load(f) except FileNotFoundError: - print('MSG\tℹ️ 未找到 openclaw.json,請先完成安裝/初始化。') + print('MSG\tℹ️ 未找到 openclaw.json,请先完成安装/初始化。') raise SystemExit(0) except Exception as e: print(f'MSG\t❌ 讀取設定失敗: {type(e).__name__}: {e}') @@ -11019,7 +11019,7 @@ if not base_url or not api_key or not isinstance(model_list, list) or not model_ raise SystemExit(3) if api not in SUPPORTED_APIS: - print(f'ℹ️ provider {target} 当前 api={api},但脚本已不再探测/纠正协议;请手动设置为 openai-completions 或 openai-responses') + print(f'ℹ️ provider {target} 目前 api={api},但腳本已不再探測/修正協定;請手動設定為 openai-completions 或 openai-responses') protocol_msg = None @@ -11137,7 +11137,7 @@ PY2 echo "❌ 同步失敗:上游 /models 請求失敗" ;; 5) - echo "❌ 同步失敗:上游模型為空或同步後無可用模型" + echo "❌ 同步失败:上游模型为空或同步后无可用模型" ;; *) echo "❌ 同步失敗:請檢查設定檔結構或日誌輸出" @@ -11500,7 +11500,7 @@ PY if command -v gum >/dev/null 2>&1; then return 0 fi - + if command -v apt >/dev/null 2>&1; then mkdir -p /etc/apt/keyrings curl -fsSL https://repo.charm.sh/apt/gpg.key | gpg --dearmor -o /etc/apt/keyrings/charm.gpg @@ -11528,9 +11528,9 @@ REPO } - + change_model() { - send_stats "換模型" + send_stats "换模型" local orange="#FF8C00" @@ -11765,7 +11765,7 @@ PYTHON_EOF install_gum install gum - + # 若 gum 不存在,降級為原始手動輸入流程 if ! command -v gum >/dev/null 2>&1 || ! gum --version >/dev/null 2>&1; then echo "--- 模型管理 ---" @@ -11820,7 +11820,7 @@ PYTHON_EOF selected_model=$(echo "$selected_model" | sed -E 's/^\([0-9]+\)[[:space:]]+//') echo "" - echo "正在檢測模型:$selected_model" + echo "正在检测模型: $selected_model" if openclaw_model_probe "$selected_model"; then openclaw_probe_status_line "可用" else @@ -12077,7 +12077,7 @@ PYTHON_EOF fi fi - echo "⚠️ plugins.allow 移除失败,请手动检查: $config_file" + echo "⚠️ plugins.allow 移除失敗,請手動檢查:$config_file" return 1 } @@ -12085,7 +12085,7 @@ PYTHON_EOF - + install_plugin() { send_stats "外掛管理" while true; do @@ -12113,7 +12113,7 @@ PYTHON_EOF echo "" echo "⚙️ 功能擴充:" echo "- [lobster] # 審批流 (附人工確認)" - echo " - [voice-call] # 语音通话能力" + echo "- [voice-call] # 語音通話能力" echo "- [nostr] # 加密隱私聊天" echo "--------------------------------------------------------" @@ -12188,7 +12188,7 @@ PYTHON_EOF failed_list="$failed_list $plugin_id" fi else - echo "🗑️ 正在删除/禁用插件: $plugin_id" + echo "🗑️ 正在刪除/停用插件:$plugin_id" openclaw plugins disable "$plugin_id" >/dev/null 2>&1 if openclaw plugins uninstall "$plugin_id"; then echo "✅ 已卸載:$plugin_id" @@ -12777,7 +12777,7 @@ PY mkdir -p "$backup_root" local tmp_payload=$(mktemp -d) || return 1 local workspaces_json=$(openclaw_get_all_agent_workspaces) - python3 -c "import json, sys, os, shutil; + python3 -c "import json, sys, os, shutil; workspaces = json.loads(sys.argv[1]); tmp_payload = sys.argv[2] for item in workspaces: aid = item['id']; ws = item['ws'] @@ -12838,7 +12838,7 @@ if os.path.isdir(agents_root): fi echo "備份模式:" - echo "1. 安全模式(默认,推荐):workspace + openclaw.json + extensions/skills/prompts/tools(如存在)" + echo "1. 安全模式(默認,建議):workspace + openclaw.json + extensions/skills/prompts/tools(如存在)" echo "2. 完整模式(含更多狀態,敏感風險較高)" read -e -p "請選擇備份模式(預設 1):" export_mode [ -z "$export_mode" ] && export_mode="1" @@ -12898,14 +12898,14 @@ if os.path.isdir(agents_root): echo "⚠️ 高風險操作:專案還原會涵蓋 OpenClaw 設定與工作區內容。" echo "⚠️ 還原前將執行 manifest/sha256 校驗、白名單恢復、gateway 停啟與健康檢查。" read -e -p "請輸入確認詞【我已知高風險並繼續還原】後繼續:" confirm_text - if [ "$confirm_text" != "我已知高風險並持續還原" ]; then + if [ "$confirm_text" != "我已知晓高风险并继续还原" ]; then echo "❌ 確認詞不匹配,已取消還原" break_end return 1 fi local archive_path - archive_path=$(openclaw_read_import_path "請輸入 OpenClaw 專案備份包路徑") + archive_path=$(openclaw_read_import_path "请输入 OpenClaw 项目备份包路径") [ -z "$archive_path" ] && { echo "❌ 未輸入備份路徑"; break_end; return 1; } local tmp_unpack @@ -12919,7 +12919,7 @@ if os.path.isdir(agents_root): while IFS= read -r rel; do [ -z "$rel" ] && continue if ! openclaw_is_safe_relpath "$rel" || ! openclaw_restore_path_allowed project "$rel"; then - echo "❌ 偵測到非法或越權路徑:$rel" + echo "❌ 检测到非法或越权路径: $rel" invalid=1 break fi @@ -12949,7 +12949,7 @@ if os.path.isdir(agents_root): echo "▶️ 還原後啟動 OpenClaw gateway..." openclaw gateway start >/dev/null 2>&1 sleep 2 - echo "🩺 gateway 健康檢查:" + echo "🩺 gateway 健康检查:" openclaw gateway status || true fi @@ -13066,7 +13066,7 @@ if os.path.isdir(agents_root): return 0 fi if [ -z "$user_input" ]; then - echo "❌ 輸入不能為空。" + echo "❌ 输入不能为空。" break_end return 1 fi @@ -13269,7 +13269,7 @@ PY ts=$(date +%Y%m%d_%H%M%S) backup_file="${store_file}.bak.${ts}" if mv "$store_file" "$backup_file"; then - echo "✅ [$agent_id] 已備份索引:$backup_file" + echo "✅ [$agent_id] 已备份索引: $backup_file" else echo "⚠️ [$agent_id] 索引備份失敗,繼續重建。" fi @@ -13466,7 +13466,7 @@ PY if [ "$qmd_ok" = "true" ]; then OPENCLAW_MEMORY_RECOMMEND_REASON+=("QMD 可用") else - OPENCLAW_MEMORY_RECOMMEND_REASON+=("未检测到 QMD") + OPENCLAW_MEMORY_RECOMMEND_REASON+=("未檢測到 QMD") fi if [ -n "$model_path" ]; then OPENCLAW_MEMORY_RECOMMEND_REASON+=("本地模型路徑:$model_path") @@ -13659,7 +13659,7 @@ PY echo "地區:$OPENCLAW_MEMORY_COUNTRY" fi if [ -n "$OPENCLAW_MEMORY_HF_BASE" ]; then - echo "下载源: $OPENCLAW_MEMORY_HF_BASE" + echo "下載來源:$OPENCLAW_MEMORY_HF_BASE" fi echo "最終狀態:" openclaw_memory_render_status @@ -13981,7 +13981,7 @@ EOF fi else echo "includeDefaultMemory 配置正常。" - echo "将执行:清理旧索引 → 全量重建所有智能体索引" + echo "將執行:清理舊索引 → 全量重建所有智能體索引" echo "" read -e -p "確認執行? (Y/n):" confirm_fix if [[ ! "$confirm_fix" =~ ^[Nn]$ ]]; then @@ -14136,11 +14136,11 @@ EOF while true; do clear echo "=======================================" - echo "OpenClaw 記憶文件" + echo "OpenClaw 记忆文件" echo "=======================================" openclaw_memory_file_render_list echo "---------------------------------------" - read -e -p "請輸入文件編號查看(0 返回):" file_choice + read -e -p "请输入文件编号查看(0 返回): " file_choice if [ "$file_choice" = "0" ]; then return 0 fi @@ -14314,7 +14314,7 @@ EOF openclaw_permission_restart_gateway() { if ! openclaw_has_command openclaw; then - echo "❌ 未检测到 openclaw,无法重启 OpenClaw Gateway。" + echo "❌ 未偵測到 openclaw,無法重新啟動 OpenClaw Gateway。" return 1 fi echo "正在重啟 OpenClaw Gateway..." @@ -14447,9 +14447,9 @@ PY local ask="$2" local fallback="$3" local approvals_file="$HOME/.openclaw/exec-approvals.json" - + mkdir -p "$HOME/.openclaw" - + # 產生 JSON 並透過 openclaw approvals set --stdin 寫入(優先) # 若 CLI 不支援則回退直接寫文件 local json_payload @@ -14472,7 +14472,7 @@ data["defaults"]["askFallback"] = sys.argv[4] data["defaults"]["autoAllowSkills"] = True print(json.dumps(data, indent=2)) ' "$approvals_file" "$sec" "$ask" "$fallback") - + if openclaw_has_command openclaw && echo "$json_payload" | openclaw approvals set --stdin >/dev/null 2>&1; then return 0 fi @@ -14508,11 +14508,11 @@ print(json.dumps(data, indent=2)) echo -e "當前綜合安全等級:${current_mode}" echo "---------------------------------------" echo -e "${gl_huang}[應用層 Tool Policy 狀態]${gl_bai}" - echo " Profile (预设): ${current_profile:-(unset)}" + echo "Profile (預設): ${current_profile:-(unset)}" echo "Exec 限制: ${current_sec:-(unset)}" echo "審核提示: ${current_ask:-(unset)}" echo "提權開關: ${current_elevated:-(unset)}" - + echo -e "\n${gl_huang}[底層 Exec Approvals 狀態]${gl_bai}" if openclaw_has_command openclaw; then local approvals_json @@ -14529,7 +14529,7 @@ try: ask = defaults.get("ask", "(unset)") fb = defaults.get("askFallback", "(unset)") auto = defaults.get("autoAllowSkills", False) - print("攔截策略 (Security):" + str(sec)) + print(" 拦截策略 (Security): " + str(sec)) print("提示策略 (Ask):" + str(ask)) print("無UI兜底 (AskFallback):" + str(fb)) print("自動放行技能 (autoAllowSkills):" + ("on" if auto else "off")) @@ -14563,7 +14563,7 @@ except Exception: openclaw_permission_apply_standard() { send_stats "OpenClaw權限-標準安全模式" openclaw_permission_require_openclaw || return 1 - + echo "正在設定應用層策略..." openclaw config set tools.profile coding >/dev/null 2>&1 openclaw config set tools.exec.security allowlist >/dev/null 2>&1 @@ -14571,10 +14571,10 @@ except Exception: openclaw config set tools.elevated.enabled false >/dev/null 2>&1 openclaw config set tools.exec.strictInlineEval true >/dev/null 2>&1 # 拦截危险的内联代码 openclaw config unset commands.bash >/dev/null 2>&1 # 废弃旧版参数 - + echo "正在設定宿主機審批攔截..." openclaw_permission_update_exec_approvals "allowlist" "on-miss" "deny" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ 已切換為標準安全模式 (所有危險命令將透過UI/TG請求你的批准)${gl_bai}" } @@ -14582,17 +14582,17 @@ except Exception: openclaw_permission_apply_developer() { send_stats "OpenClaw權限-開發增強模式" openclaw_permission_require_openclaw || return 1 - + echo "正在設定應用層策略..." openclaw config set tools.profile coding >/dev/null 2>&1 openclaw config set tools.exec.security allowlist >/dev/null 2>&1 openclaw config set tools.exec.ask on-miss >/dev/null 2>&1 openclaw config set tools.elevated.enabled true >/dev/null 2>&1 # 允许智能体申请提权 openclaw config set tools.exec.strictInlineEval false >/dev/null 2>&1 - + echo "正在設定宿主機審批攔截..." openclaw_permission_update_exec_approvals "allowlist" "on-miss" "deny" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ 已切換為開發增強模式 (允許提權,但常規危險命令仍需審批)${gl_bai}" } @@ -14600,18 +14600,18 @@ except Exception: openclaw_permission_apply_full() { send_stats "OpenClaw權限-完全開放模式" openclaw_permission_require_openclaw || return 1 - + echo "正在設定應用層策略..." openclaw config set tools.profile full >/dev/null 2>&1 openclaw config set tools.exec.security full >/dev/null 2>&1 openclaw config set tools.exec.ask off >/dev/null 2>&1 openclaw config set tools.elevated.enabled true >/dev/null 2>&1 openclaw config set tools.exec.strictInlineEval false >/dev/null 2>&1 - + echo "正在瓦解宿主機攔截防禦..." # 這裡的 full 和 off 將徹底繞過底層宿主機的 exec 審批系統 openclaw_permission_update_exec_approvals "full" "off" "full" - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ 已切換為完全開放模式 (警告:所有宿主機指令攔截已失效,智能體具有最高權限)${gl_bai}" } @@ -14619,14 +14619,14 @@ except Exception: openclaw_permission_restore_official_defaults() { send_stats "OpenClaw權限-恢復官方默認" openclaw_permission_require_openclaw || return 1 - + echo "清理應用層強制覆蓋..." openclaw config unset tools.profile >/dev/null 2>&1 openclaw config unset tools.exec.security >/dev/null 2>&1 openclaw config unset tools.exec.ask >/dev/null 2>&1 openclaw config unset tools.elevated.enabled >/dev/null 2>&1 openclaw config unset tools.exec.strictInlineEval >/dev/null 2>&1 - + echo "清理宿主機攔截配置..." # 優先透過 CLI 清空審核配置,回退直接刪文件 if echo '{"version":1,"defaults":{}}' | openclaw approvals set --stdin >/dev/null 2>&1; then @@ -14634,7 +14634,7 @@ except Exception: else rm -f "$HOME/.openclaw/exec-approvals.json" fi - + openclaw_permission_restart_gateway echo -e "${gl_lv}✅ 已恢復到 OpenClaw 官方安全沙盒防禦機制${gl_bai}" } @@ -14685,7 +14685,7 @@ except Exception as e: print("(解析失敗:" + str(e) + ")") ' "$allowlist_json" else - echo "(無法取得)" + echo " (无法获取)" fi echo "---------------------------------------" echo "1. 新增白名單規則" @@ -14697,7 +14697,7 @@ except Exception as e: 1) read -e -p "輸入要放行的命令路徑 (支援 glob,如 /usr/bin/git):" pattern [ -z "$pattern" ] && { echo "不能為空"; break_end; continue; } - read -e -p "指定智能體ID (留空=所有智能體 *):" agent_id + read -e -p "指定智能体ID (留空=所有智能体 *): " agent_id agent_id="${agent_id:-*}" openclaw approvals allowlist add --agent "$agent_id" "$pattern" break_end @@ -14975,7 +14975,7 @@ else: is_default = item.get("isDefault", False) bcount = item.get("bindings", 0) default_tag = "[預設]" if is_default else "" - print("- 智能体ID: \033[1;36m%s\033[0m%s" % (aid, default_tag)) + print("- 智能體ID: \033[1;36m%s\033[0m%s" % (aid, default_tag)) print("身份名稱: %s %s" % (identity, emoji)) print("模型: %s" % model) print("工作目錄: %s" % ws) @@ -15013,7 +15013,7 @@ for idx,item in enumerate(agents,1): echo "正在配置智能體身份..." openclaw agents set-identity --agent "$agent_id" --name "$name" --theme "$theme" else - echo "❌ 智能體創建失敗" + echo "❌ 智能體建立失敗" return 1 fi } @@ -15078,9 +15078,9 @@ for idx,item in enumerate(bindings,1): read -e -p "輸入 yes 確認繼續:" confirm [ "$confirm" = "yes" ] || { echo "已取消"; return 1; } if openclaw agents unbind --agent "$agent_id" --bind "$bind_value"; then - echo "✅ 路由绑定移除成功" + echo "✅ 路由綁定移除成功" else - echo "❌ 路由绑定移除失败" + echo "❌ 路由綁定移除失敗" return 1 fi } @@ -15275,7 +15275,7 @@ openclaw_backup_restore_menu() { npm uninstall -g openclaw crontab -l 2>/dev/null | grep -v "s gateway" | crontab - rm -rf "$HOME/.openclaw" - [ "$HOME" != "/root" ] && [ -d /root/.openclaw ] && echo "⚠️ 检测到 root 目录下仍存在 /root/.openclaw,如需清理请手动处理" + [ "$HOME" != "/root" ] && [ -d /root/.openclaw ] && echo "⚠️ 偵測到 root 目錄下仍存在 /root/.openclaw,如需清理請手動處理" hash -r sed -i "/\b${app_id}\b/d" /home/docker/appno.txt echo "卸載完成" @@ -15331,7 +15331,7 @@ openclaw_backup_restore_menu() { domains=$(openclaw_find_webui_domain) if [ -n "$domains" ]; then - echo "網域名稱地址:" + echo "網域地址:" echo "$domains" | while read d; do echo "https://${d}/#token=${token}" done @@ -15367,14 +15367,14 @@ openclaw_backup_restore_menu() { if command -v jq >/dev/null 2>&1; then tmp_json=$(mktemp) jq 'if .gateway.controlUi == null then .gateway.controlUi = {"allowedOrigins": ["http://127.0.0.1"]} else . end | if (.gateway.controlUi.allowedOrigins | contains([$origin]) | not) then .gateway.controlUi.allowedOrigins += [$origin] else . end' --arg origin "$new_origin" "$config_file" > "$tmp_json" && mv "$tmp_json" "$config_file" - echo -e "${gl_kjlan}已將域名${yuming} 加入 allowedOrigins 配置${gl_bai}" + echo -e "${gl_kjlan}已將域名${yuming}加入 allowedOrigins 配置${gl_bai}" openclaw gateway restart >/dev/null 2>&1 fi fi openclaw devices list - read -e -p "请输入 Request_Key: " Request_Key + read -e -p "請輸入 Request_Key:" Request_Key [ -z "$Request_Key" ] && { echo "Request_Key 不能為空" @@ -15428,7 +15428,7 @@ openclaw_backup_restore_menu() { - # 主循環 + # 主循环 while true; do show_menu read choice @@ -15447,7 +15447,7 @@ openclaw_backup_restore_menu() { openclaw onboard --install-daemon break_end ;; - 12) send_stats "健康檢測與修復" + 12) send_stats "健康检测与修复" openclaw doctor --fix send_stats "OpenClaw API同步觸發" if sync_openclaw_api_models; then @@ -15520,7 +15520,7 @@ while true; do echo -e "${gl_kjlan}11. ${color11}禪道專案管理軟體${gl_kjlan}12. ${color12}青龍面板定時任務管理平台" echo -e "${gl_kjlan}13. ${color13}Cloudreve網盤${gl_huang}★${gl_bai} ${gl_kjlan}14. ${color14}簡單圖床圖片管理程序" echo -e "${gl_kjlan}15. ${color15}emby多媒體管理系統${gl_kjlan}16. ${color16}Speedtest測速板" - echo -e "${gl_kjlan}17. ${color17}AdGuardHome去廣告軟體${gl_kjlan}18. ${color18}onlyoffice線上辦公OFFICE" + echo -e "${gl_kjlan}17. ${color17}AdGuardHome去廣告軟體${gl_kjlan}18. ${color18}onlyoffice在线办公OFFICE" echo -e "${gl_kjlan}19. ${color19}雷池WAF防火牆面板${gl_kjlan}20. ${color20}portainer容器管理面板" echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}21. ${color21}VScode網頁版${gl_kjlan}22. ${color22}UptimeKuma監控工具" @@ -15544,7 +15544,7 @@ while true; do echo -e "${gl_kjlan}51. ${color51}PVE開小雞面板${gl_kjlan}52. ${color52}DPanel容器管理面板" echo -e "${gl_kjlan}53. ${color53}llama3聊天AI大模型${gl_kjlan}54. ${color54}AMH主機建站管理面板" echo -e "${gl_kjlan}55. ${color55}FRP內網穿透(服務端)${gl_huang}★${gl_bai} ${gl_kjlan}56. ${color56}FRP內網穿透(客戶端)${gl_huang}★${gl_bai}" - echo -e "${gl_kjlan}57. ${color57}Deepseek聊天AI大模型 ${gl_kjlan}58. ${color58}Dify大模型知識庫${gl_huang}★${gl_bai}" + echo -e "${gl_kjlan}57. ${color57}Deepseek聊天AI大模型${gl_kjlan}58. ${color58}Dify大模型知識庫${gl_huang}★${gl_bai}" echo -e "${gl_kjlan}59. ${color59}NewAPI大模型資產管理${gl_kjlan}60. ${color60}JumpServer開源堡壘機" echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}61. ${color61}線上翻譯伺服器${gl_kjlan}62. ${color62}RAGFlow大模型知識庫" @@ -15561,24 +15561,25 @@ while true; do echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}81. ${color81}JitsiMeet視訊會議${gl_kjlan}82. ${color82}gpt-load高性能AI透明代理" echo -e "${gl_kjlan}83. ${color83}komari伺服器監控工具${gl_kjlan}84. ${color84}Wallos個人財務管理工具" - echo -e "${gl_kjlan}85. ${color85}immich圖片影片管理器${gl_kjlan}86. ${color86}jellyfin媒體管理系統" + echo -e "${gl_kjlan}85. ${color85}immich图片视频管理器 ${gl_kjlan}86. ${color86}jellyfin媒體管理系統" echo -e "${gl_kjlan}87. ${color87}SyncTV一起看片神器${gl_kjlan}88. ${color88}Owncast自架直播平台" echo -e "${gl_kjlan}89. ${color89}FileCodeBox檔案快遞${gl_kjlan}90. ${color90}matrix去中心化聊天協議" echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}91. ${color91}gitea私有程式碼倉庫${gl_kjlan}92. ${color92}FileBrowser文件管理器" - echo -e "${gl_kjlan}93. ${color93}Dufs極簡靜態檔案伺服器${gl_kjlan}94. ${color94}Gopeed高速下載工具" + echo -e "${gl_kjlan}93. ${color93}Dufs極簡靜態檔案伺服器${gl_kjlan}94. ${color94}Gopeed高速下载工具" echo -e "${gl_kjlan}95. ${color95}paperless文件管理平台${gl_kjlan}96. ${color96}2FAuth自架二步驟驗證器" echo -e "${gl_kjlan}97. ${color97}WireGuard組網(服務端)${gl_kjlan}98. ${color98}WireGuard組網(客戶端)" echo -e "${gl_kjlan}99. ${color99}DSM群暉虛擬機${gl_kjlan}100. ${color100}Syncthing點對點檔案同步工具" echo -e "${gl_kjlan}-------------------------" - echo -e "${gl_kjlan}101. ${color101}AI影片生成工具${gl_kjlan}102. ${color102}VoceChat多人線上聊天系統" + echo -e "${gl_kjlan}101. ${color101}AI影片產生工具${gl_kjlan}102. ${color102}VoceChat多人線上聊天系統" echo -e "${gl_kjlan}103. ${color103}Umami網站統計工具${gl_kjlan}104. ${color104}Stream四層代理轉送工具" echo -e "${gl_kjlan}105. ${color105}思源筆記${gl_kjlan}106. ${color106}Drawnix開源白板工具" echo -e "${gl_kjlan}107. ${color107}PanSou網盤搜尋${gl_kjlan}108. ${color108}LangBot聊天機器人" echo -e "${gl_kjlan}109. ${color109}ZFile線上網路磁碟${gl_kjlan}110. ${color110}Karakeep書籤管理" echo -e "${gl_kjlan}-------------------------" - echo -e "${gl_kjlan}111. ${color111}多格式文件转换工具 ${gl_kjlan}112. ${color112}Lucky大內網穿透工具" + echo -e "${gl_kjlan}111. ${color111}多格式檔案轉換工具${gl_kjlan}112. ${color112}Lucky大內網穿透工具" echo -e "${gl_kjlan}113. ${color113}Firefox瀏覽器${gl_kjlan}114. ${color114}OpenClaw機器人管理工具${gl_huang}★${gl_bai}" + echo -e "${gl_kjlan}115. ${color115}Hermes機器人管理工具${gl_huang}★${gl_bai}" echo -e "${gl_kjlan}-------------------------" echo -e "${gl_kjlan}第三方應用程式列表" echo -e "${gl_kjlan}想要讓你的應用程式出現在這裡?查看開發者指南:${gl_huang}https://dev.kejilion.sh/${gl_bai}" @@ -15784,7 +15785,7 @@ while true; do local docker_describe="webtop基於Ubuntu的容器。若IP無法訪問,請新增網域訪問。" - local docker_url="官網介紹: https://docs.linuxserver.io/images/docker-webtop/" + local docker_url="官网介绍: https://docs.linuxserver.io/images/docker-webtop/" local docker_use="" local docker_passwd="" local app_size="2" @@ -16073,7 +16074,7 @@ while true; do local docker_describe="禪道是通用的專案管理軟體" local docker_url="官網介紹: https://www.zentao.net/" - local docker_use="echo \"初始使用者名稱: admin\"" + local docker_use="echo \"初始用户名: admin\"" local docker_passwd="echo \"初始密碼: 123456\"" local app_size="2" docker_app @@ -16484,7 +16485,7 @@ while true; do local docker_describe="webtop基於Alpine的中文版容器。若IP無法訪問,請新增網域訪問。" - local docker_url="官網介紹: https://docs.linuxserver.io/images/docker-webtop/" + local docker_url="官网介绍: https://docs.linuxserver.io/images/docker-webtop/" local docker_use="" local docker_passwd="" local app_size="2" @@ -16544,7 +16545,7 @@ while true; do } - local docker_describe="dockge是一個可視化的docker-compose容器管理面板" + local docker_describe="dockge是一个可视化的docker-compose容器管理面板" local docker_url="官網介紹:${gh_proxy}github.com/louislam/dockge" local docker_use="" local docker_passwd="" @@ -16963,7 +16964,7 @@ while true; do } - local docker_describe="Docker Registry 是一个用于存储和分发 Docker 镜像的服务。" + local docker_describe="Docker Registry 是一個用於儲存和分發 Docker 映像的服務。" local docker_url="官網介紹: https://hub.docker.com/_/registry" local docker_use="" local docker_passwd="" @@ -17446,7 +17447,7 @@ while true; do docker run -d --name it-tools --restart=always -p ${docker_port}:80 corentinth/it-tools:latest } - local docker_describe="對開發人員和 IT 工作者來說非常有用的工具" + local docker_describe="对开发人员和 IT 工作者来说非常有用的工具" local docker_url="官網介紹:${gh_https_url}github.com/CorentinTh/it-tools" local docker_use="" local docker_passwd="" @@ -17827,7 +17828,7 @@ while true; do local docker_describe="迅雷你的離線高速BT磁力下載工具" local docker_url="官網介紹:${gh_https_url}github.com/cnk3x/xunlei" - local docker_use="echo \"手機登入迅雷,再輸入邀請碼,邀請碼: 迅雷牛通\"" + local docker_use="echo \"手机登录迅雷,再输入邀请码,邀请码: 迅雷牛通\"" local docker_passwd="" local app_size="1" docker_app @@ -18239,7 +18240,7 @@ while true; do local docker_describe="開源、免費的自建直播平台" local docker_url="官網介紹: https://owncast.online" local docker_use="echo \"訪問地址後面帶 /admin 訪問管理員頁面\"" - local docker_passwd="echo \"初始帳號: admin 初始密碼: abc123 登陸後請及時修改登入密碼\"" + local docker_passwd="echo \"初始账号: admin 初始密码: abc123 登陆后请及时修改登录密码\"" local app_size="1" docker_app @@ -18753,7 +18754,7 @@ while true; do local app_id="99" local app_name="dsm群暉虛擬機" - local app_text="Docker容器中的虚拟DSM" + local app_text="Docker容器中的虛擬DSM" local app_url="官網:${gh_https_url}github.com/vdsm/virtual-dsm" local docker_name="dsm" local docker_port="8099" @@ -18836,7 +18837,7 @@ while true; do 101|moneyprinterturbo) local app_id="101" - local app_name="AI影片生成工具" + local app_name="AI影片產生工具" local app_text="MoneyPrinterTurbo是一款使用AI大模型合成高清短影片的工具" local app_url="官方網站:${gh_https_url}github.com/harry0703/MoneyPrinterTurbo" local docker_name="moneyprinterturbo" @@ -18892,7 +18893,7 @@ while true; do } - local docker_describe="是一款支援獨立部署的個人雲端社群媒體聊天服務" + local docker_describe="是一款支持独立部署的个人云社交媒体聊天服务" local docker_url="官網介紹:${gh_https_url}github.com/Privoce/vocechat-web" local docker_use="" local docker_passwd="" @@ -18998,7 +18999,7 @@ while true; do } - local docker_describe="是一款強大的開源白板工具,整合心智圖、流程圖等。" + local docker_describe="是一款强大的开源白板工具,集成思维导图、流程图等。" local docker_url="官網介紹:${gh_https_url}github.com/plait-board/drawnix" local docker_use="" local docker_passwd="" @@ -19118,7 +19119,7 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ 110|karakeep) local app_id="110" local app_name="karakeep書籤管理" - local app_text="是一款可自行托管的书签应用,带有人工智能功能,专为数据囤积者而设计。" + local app_text="是一款可自行託管的書籤應用,具有人工智慧功能,專為資料囤積者而設計。" local app_url="官方網站:${gh_https_url}github.com/karakeep-app/karakeep" local docker_name="docker-web-1" local docker_port="8110" @@ -19186,7 +19187,7 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ local app_id="112" local docker_name="lucky" local docker_img="gdy666/lucky:v2" - # 由於 Lucky 使用 host 網路模式,這裡的連接埠僅作記錄/說明參考,實際上由應用自身控制(預設16601) + # 由于 Lucky 使用 host 网络模式,这里的端口仅作记录/说明参考,实际由应用自身控制(默认16601) local docker_port=8112 docker_rum() { @@ -19246,6 +19247,9 @@ discourse,yunsou,ahhhhfs,nsgame,gying" \ moltbot_menu ;; + 115|hermes) + bash <(curl -sL ${gh_proxy}raw.githubusercontent.com/kejilion/sh/main/hermes_manager.sh) + ;; b) clear @@ -19357,7 +19361,7 @@ linux_work() { tmux list-sessions echo -e "${gl_kjlan}------------------------" echo -e "${gl_kjlan}1. ${gl_bai}1號工作區" - echo -e "${gl_kjlan}2. ${gl_bai}2號工作區" + echo -e "${gl_kjlan}2. ${gl_bai}2号工作区" echo -e "${gl_kjlan}3. ${gl_bai}3號工作區" echo -e "${gl_kjlan}4. ${gl_bai}4號工作區" echo -e "${gl_kjlan}5. ${gl_bai}5號工作區" @@ -19462,7 +19466,7 @@ linux_work() { echo -e "SSH常駐模式${tmux_sshd_status}" echo "開啟後SSH連線後會直接進入常駐模式,直接回到先前的工作狀態。" echo "------------------------" - echo "1. 開啟 2. 關閉" + echo "1. 开启 2. 关闭" echo "------------------------" echo "0. 返回上一級選單" echo "------------------------" @@ -19684,7 +19688,7 @@ net_menu() { send_stats "啟用網卡" read -erp "請輸入要啟用的網路卡名稱:" nic if ip link show "$nic" &>/dev/null; then - ip link set "$nic" up && echo "✔ 网卡 $nic已啟用" + ip link set "$nic" up && echo "✔ 網路卡$nic已啟用" else echo "✘ 網路卡不存在" fi @@ -19807,7 +19811,7 @@ log_menu() { echo "⚠️ 清理 journal 日誌(安全方式)" echo "1) 保留最近 7 天" echo "2) 保留最近 3 天" - echo "3) 限制日志最大 500M" + echo "3) 限制日誌最大 500M" read -erp "請選擇清理方式:" c case $c in 1) journalctl --vacuum-time=7d ;; @@ -19961,7 +19965,7 @@ create_user_with_sshkey() { local sshkey_vl if [[ -z "$new_username" ]]; then - echo "用法:create_user_with_sshkey <使用者名稱>" + echo "用法:create_user_with_sshkey <用户名>" return 1 fi @@ -20031,11 +20035,11 @@ linux_Settings() { # send_stats "系統工具" echo -e "系統工具" echo -e "${gl_kjlan}------------------------" - echo -e "${gl_kjlan}1. ${gl_bai}設定腳本啟動快捷鍵${gl_kjlan}2. ${gl_bai}修改登入密碼" + echo -e "${gl_kjlan}1. ${gl_bai}设置脚本启动快捷键 ${gl_kjlan}2. ${gl_bai}修改登入密碼" echo -e "${gl_kjlan}3. ${gl_bai}使用者密碼登入模式${gl_kjlan}4. ${gl_bai}安裝Python指定版本" echo -e "${gl_kjlan}5. ${gl_bai}開放所有連接埠${gl_kjlan}6. ${gl_bai}修改SSH連接埠" echo -e "${gl_kjlan}7. ${gl_bai}優化DNS位址${gl_kjlan}8. ${gl_bai}一鍵重裝系統${gl_huang}★${gl_bai}" - echo -e "${gl_kjlan}9. ${gl_bai}停用ROOT帳戶建立新帳戶${gl_kjlan}10. ${gl_bai}切換優先ipv4/ipv6" + echo -e "${gl_kjlan}9. ${gl_bai}禁用ROOT账户创建新账户 ${gl_kjlan}10. ${gl_bai}切換優先ipv4/ipv6" echo -e "${gl_kjlan}------------------------" echo -e "${gl_kjlan}11. ${gl_bai}查看連接埠佔用狀態${gl_kjlan}12. ${gl_bai}修改虛擬記憶體大小" echo -e "${gl_kjlan}13. ${gl_bai}使用者管理${gl_kjlan}14. ${gl_bai}使用者/密碼產生器" @@ -20105,7 +20109,7 @@ linux_Settings() { echo "---------------------------------------" echo "此功能可無縫安裝python官方支援的任何版本!" local VERSION=$(python3 -V 2>&1 | awk '{print $2}') - echo -e "当前python版本号: ${gl_huang}$VERSION${gl_bai}" + echo -e "目前python版本號:${gl_huang}$VERSION${gl_bai}" echo "------------" echo "推薦版本: 3.12 3.11 3.10 3.9 3.8 2.7" echo "查詢更多版本: https://www.python.org/downloads/" @@ -20215,7 +20219,7 @@ EOF send_stats "SSH連接埠已修改" new_ssh_port $new_port elif [[ $new_port -eq 0 ]]; then - send_stats "退出SSH埠修改" + send_stats "退出SSH連接埠修改" break else echo "連接埠號碼無效,請輸入1到65535之間的數字。" @@ -20511,7 +20515,7 @@ EOF echo "1. 中國上海時間 2. 中國香港時間" echo "3. 日本東京時間 4. 韓國首爾時間" echo "5. 新加坡時間 6. 印度加爾各答時間" - echo "7. 阿聯酋杜拜時間 8. 澳洲雪梨時間" + echo "7. 阿联酋迪拜时间 8. 澳大利亚悉尼时间" echo "9. 泰國曼谷時間" echo "------------------------" echo "歐洲" @@ -20729,7 +20733,7 @@ EOF echo "" echo "操作" echo "------------------------" - echo "1. 添加新的解析 2. 删除解析地址" + echo "1. 新增新的解析 2. 刪除解析位址" echo "------------------------" echo "0. 返回上一級選單" echo "------------------------" @@ -20778,7 +20782,7 @@ EOF local rx_threshold_gb=$(grep -oP 'rx_threshold_gb=\K\d+' ~/Limiting_Shut_down.sh) local tx_threshold_gb=$(grep -oP 'tx_threshold_gb=\K\d+' ~/Limiting_Shut_down.sh) echo -e "${gl_lv}目前設定的進站限流閾值為:${gl_huang}${rx_threshold_gb}${gl_lv}G${gl_bai}" - echo -e "${gl_lv}目前設定的出站限流閾值為:${gl_huang}${tx_threshold_gb}${gl_lv}GB${gl_bai}" + echo -e "${gl_lv}当前设置的出站限流阈值为: ${gl_huang}${tx_threshold_gb}${gl_lv}GB${gl_bai}" else echo -e "${gl_hui}目前未啟用限流關機功能${gl_bai}" fi @@ -21001,9 +21005,9 @@ EOF echo -e "7. 開啟${gl_huang}BBR${gl_bai}加速" echo -e "8. 設定時區到${gl_huang}上海${gl_bai}" echo -e "9. 自動優化DNS位址${gl_huang}海外: 1.1.1.1 8.8.8.8 國內: 223.5.5.5${gl_bai}" - echo -e "10. 設定網路為${gl_huang}ipv4优先${gl_bai}" + echo -e "10. 設定網路為${gl_huang}ipv4優先${gl_bai}" echo -e "11. 安裝基礎工具${gl_huang}docker wget sudo tar unzip socat btop nano vim${gl_bai}" - echo -e "12. Linux系統核心參數優化${gl_huang}自動根據網路環境調優${gl_bai}" + echo -e "12. Linux系統核心參數優化${gl_huang}自动根据网络环境调优${gl_bai}" echo "------------------------------------------------" read -e -p "確定一鍵保養嗎? (Y/N):" choice @@ -21026,7 +21030,7 @@ EOF echo "------------------------------------------------" new_ssh_port 5522 - echo -e "[${gl_lv}OK${gl_bai}] 4/12. 設定SSH埠號為${gl_huang}5522${gl_bai}" + echo -e "[${gl_lv}OK${gl_bai}] 4/12. 设置SSH端口号为${gl_huang}5522${gl_bai}" echo "------------------------------------------------" f2b_install_sshd cd ~ @@ -21091,7 +21095,7 @@ EOF fi echo "隱私與安全" - echo "腳本將收集使用者使用功能的數據,優化腳本體驗,製作更多好玩好用的功能" + echo "脚本将收集用户使用功能的数据,优化脚本体验,制作更多好玩好用的功能" echo "將收集腳本版本號,使用的時間,系統版本,CPU架構,機器所屬國家和使用的功能的名稱," echo "------------------------------------------------" echo -e "目前狀態:$status_message" @@ -21185,7 +21189,7 @@ linux_file() { clear echo "文件管理器" echo "------------------------" - echo "目前路徑" + echo "当前路径" pwd echo "------------------------" ls --color=auto -x @@ -21193,7 +21197,7 @@ linux_file() { echo "1. 進入目錄 2. 建立目錄 3. 修改目錄權限 4. 重新命名目錄" echo "5. 刪除目錄 6. 返回上一層選單目錄" echo "------------------------" - echo "11. 建立檔案 12. 編輯檔案 13. 修改檔案權限 14. 重新命名文件" + echo "11. 建立文件 12. 編輯文件 13. 修改文件權限 14. 重新命名文件" echo "15. 刪除文件" echo "------------------------" echo "21. 壓縮檔案目錄 22. 解壓縮檔案目錄 23. 行動檔案目錄 24. 複製檔案目錄" @@ -21236,7 +21240,7 @@ linux_file() { send_stats "返回上一層選單目錄" ;; 11) # 创建文件 - read -e -p "請輸入要建立的檔案名稱:" filename + read -e -p "请输入要创建的文件名: " filename touch "$filename" && echo "文件已建立" || echo "創建失敗" send_stats "建立文件" ;; @@ -21270,7 +21274,7 @@ linux_file() { send_stats "壓縮檔案/目錄" ;; 22) # 解压文件/目录 - read -e -p "請輸入要解壓縮的檔案名稱 (.tar.gz):" filename + read -e -p "請輸入要解壓縮的檔名 (.tar.gz):" filename install tar tar -xzvf "$filename" && echo "已解壓縮$filename" || echo "解壓縮失敗" send_stats "解壓縮檔案/目錄" @@ -21297,7 +21301,7 @@ linux_file() { 24) # 复制文件目录 - read -e -p "請輸入要複製的檔案或目錄路徑:" src_path + read -e -p "请输入要复制的文件或目录路径: " src_path if [ ! -e "$src_path" ]; then echo "錯誤: 檔案或目錄不存在。" send_stats "複製檔案或目錄失敗: 檔案或目錄不存在" @@ -21442,7 +21446,7 @@ while true; do 1) send_stats "新增叢集伺服器" read -e -p "伺服器名稱:" server_name - read -e -p "服务器IP: " server_ip + read -e -p "伺服器IP:" server_ip read -e -p "伺服器連接埠(22):" server_port local server_port=${server_port:-22} read -e -p "伺服器使用者名稱(root):" server_username @@ -21544,7 +21548,7 @@ echo -e "${gl_huang}搬運工 49刀每季 美國CN2GIA 日本軟銀 2核心 1G echo -e "${gl_bai}網址: https://bandwagonhost.com/aff.php?aff=69004&pid=87${gl_bai}" echo "------------------------" echo -e "${gl_lan}DMIT 28刀每季 美國CN2GIA 1核心 2G記憶體 20G硬碟 800G流量每月${gl_bai}" -echo -e "${gl_bai}網址: https://www.dmit.io/aff.php?aff=4966&pid=100${gl_bai}" +echo -e "${gl_bai}网址: https://www.dmit.io/aff.php?aff=4966&pid=100${gl_bai}" echo "------------------------" echo -e "${gl_zi}V.PS 6.9刀每月 東京軟銀 2核心 1G內存 20G硬碟 1T流量每月${gl_bai}" echo -e "${gl_bai}網址: https://vps.hosting/cart/tokyo-cloud-kvm-vps/?id=148&?affid=1355&?affid=1355${gl_bai}" @@ -21556,7 +21560,7 @@ echo "" echo -e "網域優惠" echo "------------------------" echo -e "${gl_lan}GNAME 8.8刀首年COM域名 6.68刀首年CC域名${gl_bai}" -echo -e "${gl_bai}网址: https://www.gname.com/register?tt=86836&ttcode=KEJILION86836&ttbj=sh${gl_bai}" +echo -e "${gl_bai}網址: https://www.gname.com/register?tt=86836&ttcode=KEJILION86836&ttbj=sh${gl_bai}" echo "------------------------" echo "" echo -e "科技lion週邊" @@ -21648,7 +21652,7 @@ while true; do local sh_v_new=$(curl -s --max-time 15 -r 0-200 ${gh_proxy}raw.githubusercontent.com/kejilion/sh/main/kejilion.sh | grep -o 'sh_v="[0-9.]*"' | head -1 | cut -d '"' -f 2) if [ -z "$sh_v_new" ]; then - echo -e "${gl_hong}無法獲取最新版本信息,請檢查網絡連接${gl_bai}" + echo -e "${gl_hong}无法获取最新版本信息,请检查网络连接${gl_bai}" elif [ "$sh_v" = "$sh_v_new" ]; then echo -e "${gl_lv}你已經是最新版本!${gl_huang}v$sh_v${gl_bai}" send_stats "腳本已經最新了,無需更新" @@ -21663,7 +21667,7 @@ while true; do if [ -n "$existing_cron" ]; then echo "------------------------" - echo -e "${gl_lv}自動更新已開啟,每天凌晨2點腳本會自動更新!${gl_bai}" + echo -e "${gl_lv}自动更新已开启,每天凌晨2点脚本会自动更新!${gl_bai}" fi echo "------------------------" @@ -21686,7 +21690,7 @@ while true; do # 備份當前腳本 cp -f ~/kejilion.sh ~/kejilion.sh.bak 2>/dev/null - # 下载到临时文件,校验后再替换 + # 下載到臨時文件,校驗後再替換 local tmp_file=$(mktemp ~/kejilion_tmp.XXXXXX) if curl -sS --max-time 60 --fail -o "$tmp_file" "$download_url" && \ [ -s "$tmp_file" ] && \ @@ -21698,7 +21702,7 @@ while true; do yinsiyuanquan2 cp -f ~/kejilion.sh /usr/local/bin/k > /dev/null 2>&1 ln -sf /usr/local/bin/k /usr/bin/k > /dev/null 2>&1 - echo -e "${gl_lv}脚本已更新到最新版本!${gl_huang}v$sh_v_new${gl_bai}" + echo -e "${gl_lv}腳本已更新至最新版本!${gl_huang}v$sh_v_new${gl_bai}" send_stats "腳本已經最新$sh_v_new" else rm -f "$tmp_file" @@ -21706,7 +21710,7 @@ while true; do if [ -f ~/kejilion.sh.bak ]; then mv -f ~/kejilion.sh.bak ~/kejilion.sh fi - echo -e "${gl_hong}更新失敗!下载出错或文件校验不通过,已恢复原版本${gl_bai}" + echo -e "${gl_hong}更新失敗!下載出錯或檔案校驗不通過,已恢復原版本${gl_bai}" send_stats "腳本更新失敗" fi break_end @@ -21739,13 +21743,13 @@ while true; do SH_Update_task="$SH_Update_task && grep -q 'permission_granted=\"true\"' ~/kejilion.sh.bak 2>/dev/null && sed -i 's/permission_granted=\"false\"/permission_granted=\"true\"/' ~/kejilion.sh; grep -q 'ENABLE_STATS=\"false\"' ~/kejilion.sh.bak 2>/dev/null && sed -i 's/ENABLE_STATS=\"true\"/ENABLE_STATS=\"false\"/' ~/kejilion.sh" # 部署到 /usr/local/bin/k 和 /usr/bin/k SH_Update_task="$SH_Update_task; cp -f ~/kejilion.sh /usr/local/bin/k 2>/dev/null; ln -sf /usr/local/bin/k /usr/bin/k 2>/dev/null" - # 下載失敗時清理暫存文件 + # 下载失败时清理临时文件 SH_Update_task="$SH_Update_task || rm -f \"\$tmp\" 2>/dev/null" check_crontab_installed (crontab -l | grep -v "kejilion.sh") | crontab - (crontab -l 2>/dev/null; echo "$(shuf -i 0-59 -n 1) 2 * * * bash -c '$SH_Update_task'") | crontab - - echo -e "${gl_lv}自動更新已開啟,每天凌晨2點腳本會自動更新!${gl_bai}" + echo -e "${gl_lv}自动更新已开启,每天凌晨2点脚本会自动更新!${gl_bai}" send_stats "開啟腳本自動更新" break_end ;; @@ -21845,8 +21849,8 @@ echo "核心調優面板 k nhyh | k 核心最佳化" echo "設定虛擬記憶體 k swap 2048" echo "設定虛擬時區 k time Asia/Shanghai | k 時區 Asia/Shanghai" echo "系統回收站 k trash | k hsz | k 回收站" -echo "系統備份功能 k backup | k bf | k 備份" -echo "ssh遠端連線工具 k ssh | k 遠端連線" +echo "系统备份功能 k backup | k bf | k 备份" +echo "ssh远程连接工具 k ssh | k 远程连接" echo "rsync遠端同步工具 k rsync | k 遠端同步" echo "硬碟管理工具 k disk | k 硬碟管理" echo "內網穿透(服務端) k frps" @@ -21856,7 +21860,7 @@ echo "軟體停止 k stop sshd | k 停止 sshd" echo "軟體重啟 k restart sshd | k 重啟 sshd" echo "軟體狀態檢視 k status sshd | k 狀態 sshd" echo "軟體開機啟動 k enable docker | k autostart docke | k 開機啟動 docker" -echo "網域憑證申請 k ssl" +echo "域名证书申请 k ssl" echo "網域名稱憑證到期查詢 k ssl ps" echo "docker管理平面 k docker" echo "docker環境安裝 k docker install |k docker 安裝" @@ -21866,7 +21870,7 @@ echo "LDNMP站台管理 k web" echo "LDNMP快取清理 k web cache" echo "安裝WordPress k wp |k wordpress |k wp xxx.com" echo "安裝反向代理 k fd |k rp |k 反代 |k fd xxx.com" -echo "安装负载均衡 k loadbalance |k 负载均衡" +echo "安裝負載平衡 k loadbalance |k 負載平衡" echo "安裝L4負載平衡 k stream |k L4負載平衡" echo "防火牆面板 k fhq |k 防火牆" echo "開放埠 k dkdk 8080 |k 開啟連接埠 8080" @@ -21876,7 +21880,7 @@ echo "阻止IP k zzip 177.5.25.36 |k 阻止IP 177.5.25.36" echo "命令收藏 k fav | k 指令收藏夾" echo "應用市場管理 k app" echo "應用編號快捷管理 k app 26 | k app 1panel | k app npm" -echo "fail2ban管理 k fail2ban | k f2b" +echo "fail2ban管理 k fail2ban | k f2b" echo "顯示系統資訊 k info" echo "ROOT金鑰管理 k sshkey" echo "SSH公鑰導入(URL) k sshkey " @@ -21977,7 +21981,7 @@ else time|时区) shift - send_stats "快速設定時區" + send_stats "快速设置时区" set_timedate "$@" ;;