From e31ab788ed2c49375550117364e5cc046d3241a6 Mon Sep 17 00:00:00 2001 From: eddy Date: Sat, 1 Aug 2026 23:10:27 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E7=A7=BB=E9=99=A4=E8=BF=87=E6=97=B6?= =?UTF-8?q?=E7=9A=84=20VPS=20=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 WARP、Python 安装、留言板、重启和集群管理菜单 - 删除相关辅助函数和远程执行逻辑 - 将脚本版本提升至 3.0.0,以体现破坏性变更 - 重写功能文档并清理过时说明 --- README.md | 2 +- app.md | 411 ++++++++++++++++++++++++++++++++-------- kejilion.sh | 529 +--------------------------------------------------- 3 files changed, 334 insertions(+), 608 deletions(-) diff --git a/README.md b/README.md index ac43548..6e5b8cb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # 科技lion一键脚本工具 ## 介绍 -科技Lion 的 Shell 脚本工具是一款面向 Debian / Ubuntu VPS 的交互式管理工具箱,聚焦系统信息与维护、网络测试与调优、SSH 安全防护、流量限额控制和 VPS 集群批量运维。无论您是初学者还是经验丰富的用户,都可以通过菜单快速执行常见服务器管理任务。 +科技Lion 的 Shell 脚本工具是一款面向 Debian / Ubuntu VPS 的交互式管理工具箱,聚焦系统信息与维护、网络测试与调优、SSH 安全防护和流量限额控制。无论您是初学者还是经验丰富的用户,都可以通过菜单快速执行常见服务器管理任务。 [视频介绍](https://www.youtube.com/watch?v=0o7oH3Dit70&t=211s) *** diff --git a/app.md b/app.md index ab44f52..eb55df5 100644 --- a/app.md +++ b/app.md @@ -1,95 +1,348 @@ -本项目是一套面向 **Debian / Ubuntu VPS 的交互式服务器管理脚本工具箱**,核心程序是 `kejilion.sh`。当前功能聚焦于系统管理、网络测试与调优、安全防护、流量限额控制和 VPS 集群运维。 +已核实本地全部文件。项目核心是 `kejilion.sh`,当前版本 **v3.0.0**,定位为 **Debian / Ubuntu VPS 交互式管理工具箱**。 -## 1. VPS 系统管理 +## 一、主菜单功能 -- 查看 CPU、内存、Swap、磁盘、流量和系统负载 -- 查看操作系统、内核、主机名、IP、运营商和地理位置 -- 查看 TCP 拥塞算法、系统时间及运行时长 -- 更新系统、清理系统垃圾 -- 修改主机名、时区、DNS 和登录密码 -- 管理 Swap、用户和 sudo 权限 -- IPv4/IPv6 优先级切换 -- 查看端口占用 -- 管理 `/etc/hosts` -- 管理 Crontab 定时任务 -- 切换系统更新源(阿里云 / 官方 / 备份初始源 / 还原初始源) -- 安装 Python 指定版本(基于 pyenv) -- 重启服务器 +### 1. 系统信息查询 -> 说明:一键重装系统(dd)功能已移除。 +可以查看: -## 2. 网络与 VPS 测试 +- 主机名、系统版本、Linux 内核 +- CPU 型号、架构、核心数、占用率 +- 内存、Swap、磁盘使用情况 +- 累计接收和发送流量 +- TCP 拥塞控制算法、默认队列算法 +- 公网 IPv4、IPv6 +- IP 国家、城市、运营商 +- 系统时区、当前时间、运行时长 + +其中公网 IP 和地理信息依赖 `ip.sb`、`ipinfo.io` 等外部服务。 + +### 2. 系统更新 + +执行 Debian/Ubuntu 完整更新: + +- 更新软件索引 +- 执行 `full-upgrade` + +也支持命令行调用: + +- `./kejilion.sh update` +- `./kejilion.sh 更新` + +### 3. 系统清理 + +包括: + +- 清理无用软件包 +- 清理软件包缓存 +- 清理已删除软件的残留配置 +- 清理和轮转 systemd 日志 +- 不主动批量删除旧内核,保留回退能力 + +也支持: + +- `./kejilion.sh clean` +- `./kejilion.sh 清理` + +### 5. BBR 管理 + +提供 BBR 管理入口,但实际下载并执行第三方 `Linux-NetSpeed/tcpx.sh`。 + +因此本地只能确认有该入口,具体支持哪些 BBR 算法和操作取决于联网下载的第三方脚本。 + +另外,“系统工具”中还有一套本地实现的 **BBRv3/XanMod 内核管理**。 + +### 8. 测试脚本合集 + +#### IP 与解锁检测 + +- ChatGPT 解锁状态检测 +- Region 流媒体解锁测试 +- yeahwu 流媒体解锁检测 +- IP 质量体检 + +#### 网络线路测试 + +- BestTrace 三网回程延迟路由测试 +- MTR 三网回程线路测试 +- SuperSpeed 三网测速 +- NextTrace 快速回程测试 +- NextTrace 指定 IP 回程测试 +- ludashi2020 三网线路测试 +- i-abc 多功能测速 + +#### 性能测试 -- WARP 管理 -- ChatGPT 解锁测试 -- 流媒体解锁检测 -- IP 质量检测 -- 三网回程路由测试 -- MTR 线路测试 -- NextTrace 路由测试 -- SuperSpeed 和 i-abc 多功能测速 - YABS 性能测试 - Geekbench 5 CPU 测试 -- Bench 综合测试 +- Bench 综合性能测试 - 融合怪综合测评 -## 3. 网络加速与系统调优 - -- 开启或关闭 BBR -- BBRv3/XanMod 内核管理 -- 设置 Swap -- 配置国内或国外 DNS -- 优化时区和系统软件 - -## 4. 安全防护 - -### SSH Fail2Ban - -- SSH 防暴力破解 -- 查看 SSH 封禁状态和拦截记录 -- 实时查看 Fail2Ban 日志 -- 安装或卸载 SSH 防护 - -相关配置文件:`/path/to/fail2ban/config/fail2ban/jail.d/linux-ssh.conf` - -### 账户安全 - -- 用户管理 -- 用户和密码生成 -- 登录密码管理 - -## 5. 流量限额自动关机 - -- 设置每月流量额度 -- 定期统计接收和发送流量 -- 接收或发送任意一个方向达到阈值后自动关机(多数 VPS 只计出站,按单向判断更贴近实际配额) -- 每月重新开始统计 -- 支持启用和停用 - -相关文件:`Limiting_Shut_down.sh` - -## 6. VPS 集群批量管理 - -可以维护多台服务器列表,并批量执行: - -- 安装本项目脚本 -- 更新或清理系统 -- 安装 BBR3 -- 设置 Swap 和时区 -- 开放端口 -- 执行自定义命令 -- 导入或导出服务器列表 +这些项目大多数由第三方在线脚本完成,本地项目主要提供调用入口。 --- -总体而言,这个项目可以概括为: +## 二、系统工具 -> **VPS 系统管理 + 网络测试与调优 + SSH 安全防护 + 流量限额控制 + 集群运维。** +### 1. 设置脚本启动快捷键 -部分功能会在运行时从 GitHub 或第三方站点下载脚本和配置,因此实际可用性取决于外部资源以及目标 Debian / Ubuntu 版本。 +- 为当前脚本设置自定义 Bash 别名 +- 写入当前用户的 `~/.bashrc` +- 启动时还会尝试创建 `/usr/local/bin/k` -## 下载源说明 +### 2. 修改登录密码 -- 通过 GitHub Raw 下载的第三方脚本默认走官方地址,可通过环境变量 `GITHUB_RAW_URL` 覆盖(例如自建反代);使用项目独立域名的测试工具不受该变量控制。 -- 脚本自身的更新源由环境变量 `UPDATE_RAW_URL` 控制,默认指向本仓库的 `main` 分支。 -- 已移除按地区自动切换国内镜像的逻辑(原镜像域名已失效)。 +- 调用系统 `passwd` +- 修改当前用户密码 + +### 7. DNS 优化 + +支持: + +- 国外 DNS:Cloudflare、Google +- 国内 DNS:阿里 DNS 等 +- 同时配置 IPv4 和 IPv6 DNS + +注意:实现方式是直接修改 `/etc/resolv.conf`,可能被 `systemd-resolved`、NetworkManager 或云初始化重新覆盖。 + +### 10. IPv4/IPv6 切换 + +支持: + +- IPv4 优先 +- IPv6 优先 + +实际实现更接近: + +- IPv4 优先:禁用 IPv6 +- IPv6 优先:重新启用 IPv6 + +目前是临时 `sysctl` 设置,重启后可能失效。 + +### 11. 查看端口占用 + +使用: + +- `ss` +- 或 `netstat` +- 缺少工具时尝试安装 `iproute2` + +### 12. Swap 管理 + +可以: + +- 查看当前 Swap +- 设置新的 Swap 大小 +- 创建或替换 `/swapfile` +- 更新 `/etc/fstab` +- 调整失败时尝试恢复原来的 Swap +- 清理重复的 Swap 挂载配置 + +### 13. 用户管理 + +支持: + +- 创建普通用户 +- 创建具有 sudo 权限的用户 +- 为已有用户授予 sudo +- 撤销脚本授予的 sudo +- 删除用户 +- 查看用户主目录、用户组和 sudo 状态 + +脚本会阻止删除: + +- `root` +- 当前运行脚本的用户 +- 不存在或名称格式异常的用户 + +### 14. 用户名和密码生成器 + +可以生成: + +- 随机用户名 +- 随机英文姓名 +- UUID +- 16 位随机密码 +- 32 位随机密码 + +### 15. 系统时区管理 + +包含多个预设时区: + +- 中国上海、中国香港 +- 东京、首尔、新加坡、印度、迪拜、悉尼 +- 伦敦、巴黎、柏林、莫斯科、阿姆斯特丹、马德里 +- 美国西部、美国东部 +- 温哥华、墨西哥城、圣保罗、布宜诺斯艾利斯 + +### 16. BBRv3/XanMod 管理 + +这是本地代码中较完整的一套 BBR 功能: + +- 仅支持 Debian/Ubuntu 的 `amd64` +- 检测 CPU 的 x86-64-v1/v2/v3/v4 等级 +- 添加 XanMod APT 软件源 +- 安装对应等级的 XanMod 内核 +- 设置 BBR 拥塞算法 +- 设置 `fq_pie` 队列算法 +- 更新 BBRv3/XanMod 内核 +- 卸载 XanMod 内核 +- 卸载前确保官方回退内核存在 +- 更新 GRUB +- 操作完成后询问是否重启 + +也可以直接运行: + +- `./kejilion.sh bbr3` +- `./kejilion.sh bbrv3` + +### 18. 修改主机名 + +- 显示当前主机名 +- 校验新主机名格式 +- 使用 `hostnamectl` 修改 + +### 19. 系统更新源管理 + +支持: + +- 切换阿里云源 +- 切换官方源 +- 备份初始更新源 +- 恢复初始更新源 +- 兼容传统 `.list` 和 Deb822 `.sources` +- 修改后运行 `apt-get update` 验证 +- 验证失败时自动尝试回滚 + +### 20. Crontab 定时任务管理 + +支持: + +- 添加每月任务 +- 添加每周任务 +- 添加每天任务 +- 添加每小时任务 +- 按关键字删除任务 +- 使用 `crontab -e` 手动编辑任务 + +### 21. `/etc/hosts` 管理 + +支持: + +- 查看 hosts 内容 +- 添加解析 +- 按关键字删除解析 + +添加时没有严格校验 IP 和域名格式。 + +### 22. Fail2Ban SSH 防护 + +使用 Docker 版 LinuxServer Fail2Ban: + +- 安装并启动 Docker +- 创建 Fail2Ban 容器 +- 安装 SSH 防暴力破解配置 +- 查看 SSH Jail 状态 +- 查看拦截记录 +- 实时查看日志 +- 卸载防护程序 +- 检测和处理旧版宿主机 Fail2Ban + +配置目录为: + +- `/path/to/fail2ban/config` + +### 23. 流量限额自动关机 + +配合 `Limiting_Shut_down.sh`: + +- 设置每月流量额度 +- 每分钟检查一次流量 +- 分别统计接收和发送流量 +- 任意一个方向达到阈值即关机 +- 支持启用和停用 +- 每月 1 日 01:00 重启服务器,使内核累计流量归零 + +需要注意:它不是维护月度流量数据库,而是依靠每月重启清零累计值。 + +--- + +## 三、脚本自身功能 + +### 脚本更新 + +支持: + +- 获取远程版本号和更新日志 +- 比较本地与远程版本 +- 拒绝自动降级 +- 下载新版本 +- 执行 Bash 语法检查 +- 校验下载版本 +- 原子替换当前脚本 +- 更新 `/usr/local/bin/k` +- 自动启动新版本 + +### 软件包快捷命令 + +支持直接调用: + +- `./kejilion.sh install 软件包` +- `./kejilion.sh add 软件包` +- `./kejilion.sh remove 软件包` +- `./kejilion.sh del 软件包` + +--- + +## 四、本地辅助文件 + +### `Limiting_Shut_down.sh` + +负责: + +- 读取 `/proc/net/dev` +- 排除回环、Docker、虚拟网桥和隧道接口 +- 累计收发流量 +- 达到阈值后关机 + +### `check_x86-64_psabi.sh` + +负责检测 CPU 支持: + +- x86-64-v1 +- x86-64-v2 +- x86-64-v3 +- x86-64-v4 + +用于选择对应的 XanMod 内核。不过主脚本当前运行时会下载远程同名文件,而不是直接使用本地文件。 + +### `archive.key` + +XanMod 软件源的 PGP 公钥。主脚本目前同样下载远程版本,没有直接读取本地文件。 + +### `sshd.local` + +包含 Fail2Ban SSH Jail 配置,但当前主脚本没有引用它,应属于备用或遗留文件。 + +--- + +## 五、核实后发现的文档偏差 + +`app.md` 的总体描述基本符合代码,但有几项需要修正或注明: + +- “系统负载”无法确认:代码显示 CPU 占用率,但没有显示标准的 Load Average。 +- “开启或关闭 BBR”:本地可以确认 BBRv3 安装、更新和卸载内核;普通 BBR 的关闭功能取决于远程 `tcpx.sh`。 +- 流媒体检测、测速和性能测试大多是第三方脚本入口,并非本仓库自行实现。 +- “每月重新统计流量”实际通过每月重启服务器清零,并非独立月度计费系统。 + +## 最终概括 + +本地项目实际提供五大类功能: + +1. **VPS 系统信息、更新与清理** +2. **用户、Swap、DNS、时区、更新源等系统管理** +3. **BBR、网络线路与性能测试** +4. **Fail2Ban SSH 防护和流量限额关机** +5. **脚本自更新和命令行快捷操作** + +其中系统管理、账户、Swap、更新源、Crontab、hosts、BBRv3 和限流功能有较完整的本地实现;普通 BBR 菜单和多数测试功能主要依赖远程脚本。 \ No newline at end of file diff --git a/kejilion.sh b/kejilion.sh index 2e666da..5505d9f 100644 --- a/kejilion.sh +++ b/kejilion.sh @@ -1,6 +1,6 @@ #!/bin/bash -sh_v="2.7.0" +sh_v="3.0.0" huang='\033[33m' bai='\033[0m' @@ -439,16 +439,6 @@ ensure_swap() { add_swap } -cluster_python3() { - if [ ! -d ~/cluster ]; then - err_msg "集群环境尚未安装,请先执行“1. 安装集群环境”。" - return 1 - fi - download_file "${GITHUB_RAW_URL}/kejilion/python-for-vps/main/cluster/${py_task}" ~/cluster/"$py_task" || return 1 - python3 ~/cluster/"$py_task" -} - - f2b_status() { docker restart fail2ban sleep 3 @@ -879,10 +869,8 @@ echo "1. 系统信息查询" echo "2. 系统更新" echo "3. 系统清理" echo "5. BBR管理 ▶" -echo "7. WARP管理 ▶ " echo "8. 测试脚本合集 ▶ " echo "13. 系统工具 ▶ " -echo "14. VPS集群控制 ▶ " echo "------------------------" echo "00. 脚本更新" echo "------------------------" @@ -1026,20 +1014,6 @@ case $choice in rm -rf "$tcpx_dir" ;; - 7) - clear - warp_dir=$(mktemp -d) || { - err_msg "无法创建临时目录。" - echo "按任意键继续..." - read -n 1 -s -r -p "" - continue - } - if download_file "https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh" "${warp_dir}/menu.sh"; then - bash "${warp_dir}/menu.sh" - fi - rm -rf "$warp_dir" - ;; - 8) while true; do clear @@ -1190,7 +1164,6 @@ case $choice in echo "▶ 系统工具" echo "------------------------" echo "1. 设置脚本启动快捷键 2. 修改登录密码" - echo "4. 安装Python指定版本" echo "7. 优化DNS地址 10. 切换优先ipv4/ipv6" echo "------------------------" echo "11. 查看端口占用状态 12. 修改虚拟内存大小" @@ -1202,10 +1175,6 @@ case $choice in echo "21. 本机host解析 22. fail2banSSH防御程序" echo "23. 限流自动关机" echo "------------------------" - echo "31. 留言板" - echo "------------------------" - echo "99. 重启服务器" - echo "------------------------" echo "0. 返回主菜单" echo "------------------------" read -p "请输入你的选择: " sub_choice @@ -1228,93 +1197,6 @@ case $choice in echo "设置你的登录密码" passwd ;; - 4) - root_use - VERSION=$(python3 -V 2>&1 | awk '{print $2}') - echo -e "当前python版本号: ${huang}$VERSION${bai}" - echo "------------" - echo "推荐版本: 3.12 3.11 3.10 3.9 3.8 2.7" - echo "查询更多版本: https://www.python.org/downloads/" - echo "------------" - read -p "输入你要安装的python版本号: " py_new_v - - if ! [[ "$py_new_v" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]; then - err_msg "版本号格式不正确,示例: 3.12 或 3.12.4" - break - fi - - pyenv_installer="" - if [ ! -x "$HOME/.pyenv/bin/pyenv" ]; then - if ! install git build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \ - libsqlite3-dev wget curl llvm libncurses-dev xz-utils tk-dev \ - libffi-dev liblzma-dev libgdbm-dev libnss3-dev libedit-dev; then - err_msg "Python 编译依赖安装失败。" - break - fi - - pyenv_installer=$(mktemp) || { - err_msg "无法创建 pyenv 安装临时文件。" - break - } - if ! download_file https://pyenv.run "$pyenv_installer" || ! bash "$pyenv_installer"; then - rm -f "$pyenv_installer" - err_msg "pyenv 安装失败。" - break - fi - rm -f "$pyenv_installer" - fi - - touch "$HOME/.bashrc" || { - err_msg "无法更新 $HOME/.bashrc。" - break - } - if ! grep -Fqx 'export PYENV_ROOT="$HOME/.pyenv"' "$HOME/.bashrc"; then - cat << EOF >> ~/.bashrc - -export PYENV_ROOT="\$HOME/.pyenv" -if [[ -d "\$PYENV_ROOT/bin" ]]; then - export PATH="\$PYENV_ROOT/bin:\$PATH" -fi -eval "\$(pyenv init --path)" -eval "\$(pyenv init -)" -if pyenv commands 2>/dev/null | grep -qx virtualenv-init; then - eval "\$(pyenv virtualenv-init -)" -fi - -EOF - - fi - - export PYENV_ROOT="$HOME/.pyenv" - export PATH="$PYENV_ROOT/bin:$PATH" - if ! command -v pyenv &>/dev/null; then - err_msg "pyenv 未安装成功。" - break - fi - eval "$(pyenv init -)" - - version_pattern=${py_new_v//./\\.} - if [[ "$py_new_v" =~ ^[0-9]+\.[0-9]+$ ]]; then - version_pattern="^${version_pattern}\\.[0-9]+$" - else - version_pattern="^${version_pattern}$" - fi - py_target=$(pyenv install --list 2>/dev/null | sed 's/^[[:space:]]*//' | - grep -E "$version_pattern" | sort -V | tail -n 1) - if [ -z "$py_target" ]; then - err_msg "未找到可安装的稳定版本: $py_new_v" - break - fi - if pyenv install -s "$py_target" && pyenv global "$py_target"; then - hash -r - VERSION=$("$PYENV_ROOT/shims/python" -V 2>&1 | awk '{print $2}') - echo -e "当前python版本号: ${huang}$VERSION${bai}" - else - err_msg "Python $py_target 安装或启用失败。" - fi - - ;; - 7) root_use echo "当前DNS地址" @@ -2399,48 +2281,6 @@ EOF ;; - 31) - clear - install sshpass - - remote_ip="66.42.61.110" - remote_user="liaotian123" - remote_file="/home/liaotian123/liaotian.txt" - password="kejilionYYDS" # 替换为您的密码 - - clear - echo "科技lion留言板" - echo "------------------------" - # 显示已有的留言内容 - sshpass -p "${password}" ssh -o StrictHostKeyChecking=no "${remote_user}@${remote_ip}" "cat '${remote_file}'" - echo "" - echo "------------------------" - - # 判断是否要留言 - read -p "是否要留言?(y/n): " leave_message - - if [ "$leave_message" == "y" ] || [ "$leave_message" == "Y" ]; then - # 输入新的留言内容 - read -p "输入你的昵称: " nicheng - read -p "输入你的聊天内容: " neirong - - # 添加新留言到远程文件 - sshpass -p "${password}" ssh -o StrictHostKeyChecking=no "${remote_user}@${remote_ip}" "echo -e '${nicheng}: ${neirong}' >> '${remote_file}'" - echo "已添加留言: " - echo "${nicheng}: ${neirong}" - echo "" - else - echo "您选择了不留言。" - fi - - echo "留言板操作完成。" - - ;; - - 99) - clear - server_reboot - ;; 0) kejilion @@ -2454,373 +2294,6 @@ EOF done ;; - 14) - clear - while true; do - clear - echo "▶ VPS集群控制" - echo "你可以远程操控多台VPS一起执行任务(仅支持Ubuntu/Debian)" - echo "------------------------" - echo "1. 安装集群环境" - echo "------------------------" - echo "2. 集群控制中心" - echo "------------------------" - echo "7. 备份集群环境" - echo "8. 还原集群环境" - echo "9. 卸载集群环境" - echo "------------------------" - echo "0. 返回主菜单" - echo "------------------------" - read -p "请输入你的选择: " sub_choice - - case $sub_choice in - 1) - clear - install python3 python3-paramiko speedtest-cli lrzsz || break - mkdir -p ~/cluster || break - if [ -f ~/cluster/servers.py ]; then - echo "集群环境已存在,未覆盖现有服务器列表 ~/cluster/servers.py" - else - cat > ~/cluster/servers.py << EOF -servers = [ - -] -EOF - if chmod 600 ~/cluster/servers.py; then - echo "集群环境已初始化: ~/cluster/servers.py" - else - err_msg "集群环境已创建,但无法收紧服务器列表文件权限。" - fi - fi - - ;; - 2) - - while true; do - clear - if [ ! -f ~/cluster/servers.py ]; then - err_msg "集群环境尚未安装,请先执行“1. 安装集群环境”。" - break - fi - if ! chmod 600 ~/cluster/servers.py; then - err_msg "无法收紧服务器列表文件权限。" - break - fi - echo "集群服务器列表" - if ! python3 - "$HOME/cluster/servers.py" <<'PY' -import ast -import sys -from pathlib import Path - -path = Path(sys.argv[1]) -tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) -assignment = next( - ( - node - for node in tree.body - if isinstance(node, ast.Assign) - and any(isinstance(target, ast.Name) and target.id == "servers" for target in node.targets) - ), - None, -) -if assignment is None: - raise SystemExit("servers.py 格式异常,未找到 servers 列表") -servers = ast.literal_eval(assignment.value) -if not isinstance(servers, list) or not all(isinstance(item, dict) for item in servers): - raise SystemExit("servers.py 中的 servers 必须是字典列表") -if not servers: - print("(空)") -for index, item in enumerate(servers, 1): - print( - f"{index}. {item.get('name', '')} " - f"{item.get('hostname', '')}:{item.get('port', '')} " - f"用户: {item.get('username', '')}" - ) -PY - then - err_msg "服务器列表格式异常,请先修复或还原 servers.py。" - break - fi - - echo "" - echo "操作" - echo "------------------------" - echo "1. 添加服务器 2. 删除服务器 3. 编辑服务器" - echo "------------------------" - echo "11. 安装科技lion脚本 12. 更新系统 13. 清理系统" - echo "15. 安装BBR3 16. 设置1G虚拟内存" - echo "17. 设置时区到上海 18. 开放所有端口" - echo "------------------------" - echo "51. 自定义指令" - echo "------------------------" - echo "0. 返回上一级选单" - echo "------------------------" - read -p "请输入你的选择: " sub_choice - - case $sub_choice in - 1) - read -p "服务器名称: " server_name - read -p "服务器IP: " server_ip - read -p "服务器端口(22): " server_port - server_port=${server_port:-22} - read -p "服务器用户名(root): " server_username - server_username=${server_username:-root} - read -s -p "服务器用户密码: " server_password - echo "" - - if [ -z "$server_name" ] || [ -z "$server_ip" ]; then - err_msg "服务器名称和 IP 不能为空。" - elif ! [[ "$server_port" =~ ^[0-9]+$ ]] || [ "$server_port" -lt 1 ] || [ "$server_port" -gt 65535 ]; then - err_msg "服务器端口必须是 1 到 65535 之间的整数。" - elif ! python3 - "$HOME/cluster/servers.py" "$server_name" "$server_ip" "$server_port" "$server_username" 3<<< "$server_password" <<'PY' -import ast -import os -import pprint -import sys -import tempfile -from pathlib import Path - -path = Path(sys.argv[1]) -entry = { - "name": sys.argv[2], - "hostname": sys.argv[3], - "port": int(sys.argv[4]), - "username": sys.argv[5], - "password": os.fdopen(3).read().rstrip("\n"), - "remote_path": "/home/", -} -content = path.read_text(encoding="utf-8") -tree = ast.parse(content, filename=str(path)) -assignment = next( - ( - node - for node in tree.body - if isinstance(node, ast.Assign) - and any(isinstance(target, ast.Name) and target.id == "servers" for target in node.targets) - ), - None, -) -if assignment is None: - raise SystemExit("servers.py 格式异常,未找到 servers 列表") -servers = ast.literal_eval(assignment.value) -if not isinstance(servers, list) or not all(isinstance(item, dict) for item in servers): - raise SystemExit("servers.py 中的 servers 必须是字典列表") -servers.append(entry) - -updated = "servers = " + pprint.pformat(servers, width=120) + "\n" -fd, temp_name = tempfile.mkstemp(prefix=f".{path.name}.", dir=path.parent) -try: - with os.fdopen(fd, "w", encoding="utf-8") as handle: - handle.write(updated) - handle.flush() - os.fsync(handle.fileno()) - os.chmod(temp_name, 0o600) - os.replace(temp_name, path) -finally: - if os.path.exists(temp_name): - os.unlink(temp_name) -PY - then - err_msg "写入服务器配置失败。" - fi - - ;; - 2) - read -p "请输入需要删除的关键字: " rmserver - # 通过解析 Python 字面量删除条目,避免按行删除破坏列表结构 - if [ -z "$rmserver" ]; then - err_msg "关键字不能为空,已取消删除。" - elif ! python3 - "$HOME/cluster/servers.py" "$rmserver" <<'PY' -import ast -import os -import pprint -import sys -import tempfile -from pathlib import Path - -path = Path(sys.argv[1]) -keyword = sys.argv[2] -content = path.read_text(encoding="utf-8") -tree = ast.parse(content, filename=str(path)) -assignment = next( - ( - node - for node in tree.body - if isinstance(node, ast.Assign) - and any(isinstance(target, ast.Name) and target.id == "servers" for target in node.targets) - ), - None, -) -if assignment is None: - raise SystemExit("servers.py 格式异常,未找到 servers 列表") -servers = ast.literal_eval(assignment.value) -if not isinstance(servers, list) or not all(isinstance(item, dict) for item in servers): - raise SystemExit("servers.py 中的 servers 必须是字典列表") -remaining = [item for item in servers if keyword not in " ".join(str(value) for value in item.values())] -removed = len(servers) - len(remaining) -if removed == 0: - print("未找到匹配的服务器条目。") - raise SystemExit(0) - -updated = "servers = " + pprint.pformat(remaining, width=120) + "\n" -fd, temp_name = tempfile.mkstemp(prefix=f".{path.name}.", dir=path.parent) -try: - with os.fdopen(fd, "w", encoding="utf-8") as handle: - handle.write(updated) - handle.flush() - os.fsync(handle.fileno()) - os.chmod(temp_name, 0o600) - os.replace(temp_name, path) -finally: - if os.path.exists(temp_name): - os.unlink(temp_name) -print(f"已删除 {removed} 条服务器记录。") -PY - then - err_msg "删除服务器配置失败,原文件保持不变。" - fi - ;; - 3) - install nano - nano ~/cluster/servers.py - ;; - 11) - py_task=install_kejilion.py - cluster_python3 - ;; - 12) - py_task=update.py - cluster_python3 - ;; - 13) - py_task=clean.py - cluster_python3 - ;; - 15) - py_task=install_bbr3.py - cluster_python3 - ;; - 16) - py_task=swap1024.py - cluster_python3 - ;; - 17) - py_task=time_shanghai.py - cluster_python3 - ;; - 18) - py_task=firewall_close.py - cluster_python3 - ;; - 51) - - read -p "请输入批量执行的命令: " mingling - if [ -z "$mingling" ]; then - err_msg "命令不能为空。" - break - fi - py_task=custom_tasks.py - mkdir -p ~/cluster || break - custom_task_tmp=$(mktemp "$HOME/cluster/.custom_tasks.py.XXXXXX") || { - err_msg "无法创建自定义任务临时文件。" - break - } - if download_file "${GITHUB_RAW_URL}/kejilion/python-for-vps/main/cluster/${py_task}" "$custom_task_tmp"; then - if CUSTOM_TASK="$mingling" python3 - "$custom_task_tmp" <<'PY' -import os -import re -import sys -from pathlib import Path - -path = Path(sys.argv[1]) -content = path.read_text(encoding="utf-8") -# 上游可能用单引号也可能用双引号包裹占位符,两种都要认 -pattern = re.compile(r"""(['"])Customtasks\1""") -if not pattern.search(content): - raise SystemExit("自定义任务脚本格式异常:未找到 Customtasks 占位符") -# 用 lambda 返回替换串,避免命令里的反斜杠被 re.sub 当作转义序列二次解释 -path.write_text( - pattern.sub(lambda _: repr(os.environ["CUSTOM_TASK"]), content, count=1), - encoding="utf-8", -) -PY - then - if mv -f "$custom_task_tmp" ~/cluster/"$py_task"; then - python3 ~/cluster/"$py_task" - else - rm -f "$custom_task_tmp" - err_msg "自定义任务脚本安装失败。" - fi - else - rm -f "$custom_task_tmp" - err_msg "自定义任务脚本生成失败。" - fi - else - rm -f "$custom_task_tmp" - fi - ;; - 0) - break # 跳出循环,退出菜单 - ;; - - *) - break # 跳出循环,退出菜单 - ;; - esac - done - - ;; - 7) - clear - if [ ! -f ~/cluster/servers.py ]; then - err_msg "集群环境尚未安装,请先执行“1. 安装集群环境”。" - else - echo "将下载服务器列表数据,按任意键下载!" - read -n 1 -s -r -p "" - sz -y ~/cluster/servers.py - fi - - ;; - - 8) - clear - echo "请上传您的servers.py,按任意键开始上传!" - read -n 1 -s -r -p "" - mkdir -p ~/cluster && (cd ~/cluster/ && rz -y) - ;; - - 9) - - clear - read -p "请先备份环境,确定要卸载集群控制环境吗?(Y/N): " choice - case "$choice" in - [Yy]) - remove python3-paramiko speedtest-cli lrzsz - rm -rf ~/cluster/ - ;; - [Nn]) - echo "已取消" - ;; - *) - echo "无效的选择,请输入 Y 或 N。" - ;; - esac - - ;; - - 0) - kejilion - ;; - *) - echo "无效的输入!" - ;; - esac - break_end - - done - - ;; - 00) clear echo "更新日志"