chore: 移除过时的 VPS 管理功能
- 移除 WARP、Python 安装、留言板、重启和集群管理菜单 - 删除相关辅助函数和远程执行逻辑 - 将脚本版本提升至 3.0.0,以体现破坏性变更 - 重写功能文档并清理过时说明
This commit is contained in:
@@ -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)
|
||||
***
|
||||
|
||||
|
||||
@@ -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 菜单和多数测试功能主要依赖远程脚本。
|
||||
+1
-528
@@ -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 "更新日志"
|
||||
|
||||
Reference in New Issue
Block a user