3x-ui/docs/x-ui-logic.md
root f5862abc2e feat: add CodeMirror YAML editor for Clash template and fix settings save button bug
- Replace plain textarea with CodeMirror editor (YAML syntax highlighting, line numbers, auto-indent) for Clash subscription template
- Fix confAlerts crash when subClashURI/subURI/subJsonURI is null/undefined (prevented save button from enabling)
- Add yaml.js CodeMirror mode asset
- Include docs and .gitignore cleanup
2026-04-24 16:15:22 +08:00

27 KiB
Raw Blame History

x-ui.sh 逻辑文档

概述

x-ui.sh 是 3x-ui 面板的管理脚本,提供 26 个交互式菜单选项和 15 个子命令涵盖面板的安装、更新、卸载、凭据管理、服务控制、SSL 证书、防火墙、Fail2ban IP 限制、BBR 加速、Geo 文件更新等功能。


全局配置

颜色变量

变量 用途
red \033[0;31m 红色
green \033[0;32m 绿色
blue \033[0;34m 蓝色
yellow \033[0;33m 黄色
plain \033[0m 重置

日志函数

函数 前缀 用途
LOGD() [调试] 调试信息
LOGE() [错误] 错误信息
LOGI() [信息] 普通信息

路径变量

变量 默认值 说明
xui_folder /usr/local/x-ui x-ui 安装目录
xui_service /etc/systemd/system systemd 服务文件目录
log_folder /var/log/x-ui 日志目录
iplimit_log_path .../3xipl.log IP 限制日志
iplimit_banned_log_path .../3xipl-banned.log IP 封禁日志

辅助函数

函数 功能
confirm() 通用确认提示,支持自定义默认值
confirm_restart() 确认后重启面板(重启 x-ui 也会重启 xray
before_show_menu() 按回车返回主菜单
gen_random_string() 通过 openssl 生成指定长度的随机字母数字字符串
is_port_in_use() 端口占用检测ss → netstat → lsof
is_ipv4/is_ipv6/is_ip/is_domain() IP/域名格式验证

入口流程

x-ui.sh 被执行
  ├─ 检查 root 权限
  ├─ 检测操作系统发行版和版本号
  ├─ 初始化路径和日志目录
  │
  ├─ 有命令行参数 → 执行对应子命令(不显示菜单)
  └─ 无参数 → 显示交互式菜单 show_menu()
       ├─ 显示当前状态(运行/停止/未安装 + 开机自启 + xray 状态)
       ├─ 读取用户输入 [0-26]
       └─ 根据选择调用对应功能

主菜单 (show_menu)

╔────────────────────────────────────────────────╗
│  0.  退出脚本                                  │
│────────────────────────────────────────────────│
│  1.  安装          2.  更新          3.  更新菜单  │
│  4.  安装旧版本    5.  卸载                      │
│────────────────────────────────────────────────│
│  6.  重置用户名和密码  7.  重置 Web 路径         │
│  8.  重置设置          9.  修改端口              │
│ 10.  查看当前设置                                │
│────────────────────────────────────────────────│
│ 11.  启动    12.  停止    13.  重启              │
│ 14.  重启 Xray    15.  查看状态                  │
│ 16.  日志管理                                     │
│────────────────────────────────────────────────│
│ 17.  设置开机自启    18.  取消开机自启           │
│────────────────────────────────────────────────│
│ 19.  SSL 证书管理    20.  Cloudflare SSL         │
│ 21.  IP 限制管理     22.  防火墙管理              │
│ 23.  SSH 端口转发管理                            │
│────────────────────────────────────────────────│
│ 24.  BBR 管理    25.  更新 Geo 文件              │
│ 26.  网速测试 (Speedtest)                        │
╚────────────────────────────────────────────────╝

大部分选项在执行前调用 check_install(检查面板是否已安装)或 check_uninstall(检查面板是否未安装),防止误操作。


状态检测函数

函数 返回值 逻辑
check_status() 0=运行中, 1=未运行, 2=未安装 Alpine 检查 init.d其他检查 systemd
check_enabled() 0=已启用, 1=未启用 Alpine 检查 rc-update其他检查 systemctl
check_xray_status() 0=运行中, 1=未运行 ps 查找 xray-linux 进程
check_install() 前置检查 未安装则提示并返回菜单
check_uninstall() 前置检查 已安装则提示"勿重复安装"并返回菜单

菜单选项详解

选项 0退出脚本

exit 0

直接退出,无额外逻辑。


选项 1安装

函数install()

下载并执行 install.sh从 GitHub raw 文件)
  └─ 成功后自动调用 start()
  • 执行 bash <(curl -Ls https://raw.githubusercontent.com/Sora39831/3x-ui/main/install.sh)
  • 安装成功后自动启动面板

选项 2更新

函数update()

确认提示:"更新所有 x-ui 组件到最新版本,数据不会丢失"
  ├─ 取消 → 返回菜单
  └─ 确认 → 执行 update.sh从 GitHub 下载)
       └─ 成功 → "更新完成,面板已自动重启"

选项 3更新菜单

函数update_menu()

确认提示
  └─ 确认 → 下载最新 x-ui.sh 到 /usr/bin/x-ui
       └─ 成功 → "更新成功" 并 exit 0

仅更新管理脚本自身,不影响面板程序。


选项 4安装旧版本

函数legacy_version()

提示用户输入版本号(如 2.4.0
  ├─ 空 → 退出
  └─ 有效 → 执行对应版本的 install.sh传入版本参数
  • 下载指定 tag 的 install.shv$tag_version/install.sh
  • 传入参数 v$tag_version 进行安装
  • install.sh 内部会验证版本 ≥ v2.3.5

选项 5卸载

函数uninstall()

确认:"卸载面板xray 也会被卸载!"(默认 n
  ├─ 取消 → 返回菜单
  └─ 确认 →
      Alpine: rc-service stop → rc-update del → rm init.d
      其他:   systemctl stop → disable → rm service → daemon-reload → reset-failed
      删除 /etc/x-ui/ 和 ${xui_folder}/
      显示重装命令
      删除脚本自身trap SIGTERM → rm $0

选项 6重置用户名和密码

函数reset_user()

确认提示(默认 n
  └─ 确认 →
      输入用户名(默认随机 10 位)
      输入密码(默认随机 18 位)
      询问是否禁用双因素认证
        ├─ 是 → -resetTwoFactor true
        └─ 否 → -resetTwoFactor false
      应用设置x-ui setting -username ... -password ...
      确认后重启面板

选项 7重置 Web 路径

函数reset_webbasepath()

确认提示
  └─ 确认 → 生成随机 18 位字符串
      应用x-ui setting -webBasePath ...
      重启面板

选项 8重置设置

函数reset_config()

确认:"重置所有面板设置?账户数据不会丢失,用户名和密码不会改变"(默认 n
  └─ 确认 → x-ui setting -reset
      重启面板

仅重置面板配置,不影响账户数据库。


选项 9修改端口

函数set_port()

输入端口号 [1-65535]
  ├─ 空 → 取消
  └─ 有效 → x-ui setting -port ${port}
       确认后重启面板

选项 10查看当前设置

函数check_config()

获取面板设置x-ui setting -show true
获取公网 IPapi.ipify.org → 4.ident.me

检查是否有证书:
  ├─ 有证书 → 从证书路径提取域名,显示 https://域名:端口/路径
  └─ 无证书 →
      显示警告
      询问是否为 IP 生成 SSL 证书
        ├─ 是 → 停止面板 → ssl_cert_issue_for_ip() → 启动面板
        └─ 否 → 显示 http://IP:端口/路径,建议使用选项 19

选项 11启动

函数start()

检查当前状态
  ├─ 运行中 → "面板正在运行,无需重复启动"
  └─ 未运行 →
      Alpine: rc-service x-ui start
      其他:   systemctl start x-ui
      等待 2 秒后再次检查状态
        ├─ 成功 → "x-ui 启动成功"
        └─ 失败 → "面板启动失败,可能是因为启动时间超过两秒"

选项 12停止

函数stop()

检查当前状态
  ├─ 已停止 → "面板已停止,无需重复停止!"
  └─ 运行中 →
      Alpine: rc-service x-ui stop
      其他:   systemctl stop x-ui
      等待 2 秒后检查状态
        ├─ 成功 → "x-ui 和 xray 已停止"
        └─ 失败 → "面板停止失败"

选项 13重启

函数restart()

Alpine: rc-service x-ui restart
其他:   systemctl restart x-ui
等待 2 秒后检查状态
  ├─ 成功 → "x-ui 和 xray 重启成功"
  └─ 失败 → "面板重启失败"

选项 14重启 Xray

函数restart_xray()

systemctl reload x-ui    ← 发送 reload 信号,不重启面板本身
"已发送重启信号,请查看日志确认"
等待 2 秒 → 显示 xray 运行状态

与选项 13 的区别:选项 13 重启整个 x-ui 服务,选项 14 仅重载 xray-core。


选项 15查看状态

函数status()

Alpine: rc-service x-ui status
其他:   systemctl status x-ui -l

显示完整的 systemd/服务状态信息。


选项 16日志管理

函数show_log()

Alpine:
  1. 调试日志 → grep 'x-ui[' /var/log/messages
  0. 返回

其他 (systemd):
  1. 调试日志 → journalctl -u x-ui -e --no-pager -f -p debug
  2. 清除所有日志 → journalctl --rotate → --vacuum-time=1s → 重启面板
  0. 返回

选项 17设置开机自启

函数enable()

Alpine: rc-update add x-ui default
其他:   systemctl enable x-ui

选项 18取消开机自启

函数disable()

Alpine: rc-update del x-ui
其他:   systemctl disable x-ui

选项 19SSL 证书管理

函数ssl_cert_issue_main() — 子菜单入口

子菜单

1. 获取 SSL域名
2. 吊销证书
3. 强制续期
4. 查看已有域名
5. 为面板设置证书路径
6. 为 IP 地址获取 SSL6 天证书,自动续期)
0. 返回主菜单

子选项 1获取 SSL域名证书

函数ssl_cert_issue()

检查/安装 acme.sh
按发行版安装 socat

获取并验证域名(循环直到有效)
检查是否已有该域名的证书acme.sh --list

创建证书目录 /root/cert/${domain}/

选择端口(默认 80

签发证书:
  acme.sh --issue -d ${domain} --listen-v6 --standalone --httpport ${WebPort} --force
  ↳ 失败 → 清理并退出

设置 reloadcmd
  默认x-ui restart
  可选systemctl reload nginx ; x-ui restart
  可选:自定义命令

安装证书:
  acme.sh --installcert
    --key-file     /root/cert/${domain}/privkey.pem
    --fullchain-file /root/cert/${domain}/fullchain.pem
    --reloadcmd    ${reloadCmd}

启用自动续期acme.sh --upgrade --auto-upgrade
设置文件权限privkey.pem → 600, fullchain.pem → 644

询问是否为面板设置证书:
  ├─ 是 → x-ui cert -webCert ... -webCertKey ... → 重启
  └─ 否 → 跳过

子选项 2吊销证书

列出 /root/cert/ 下所有域名目录
选择域名 → acme.sh --revoke -d ${domain}

子选项 3强制续期

列出所有域名
选择域名 → acme.sh --renew -d ${domain} --force

子选项 4查看已有域名

遍历 /root/cert/ 下的域名目录
显示每个域名的 fullchain.pem 和 privkey.pem 路径
缺失文件的标记为"证书或密钥缺失"

子选项 5为面板设置证书路径

列出所有域名
选择域名 → 验证文件存在
  x-ui cert -webCert ... -webCertKey ...
  重启面板

子选项 6为 IP 地址获取 SSL

函数ssl_cert_issue_for_ip()

获取服务器公网 IPapi.ipify.org → 4.ident.me
询问是否包含 IPv6 地址
检查/安装 acme.sh
按发行版安装 socat

创建证书目录 /root/cert/ip/
构建域名参数:-d ${server_ip} [-d ${ipv6}]

选择 HTTP-01 监听端口(默认 80
  └─ 循环检测端口占用,被占用则提示换端口

签发证书:
  acme.sh --issue
    -d ${server_ip} [-d ${ipv6}]
    --standalone --server letsencrypt
    --certificate-profile shortlived
    --days 6 --httpport ${WebPort} --force

安装证书(不依赖退出码,通过检查文件判断成功)
启用自动续期
设置文件权限

为面板设置证书路径 → 显示 https://IP:端口/路径 → 重启面板

选项 20Cloudflare SSL 证书

函数ssl_cert_issue_CF()

显示使用说明(需要:邮箱、全局 API 密钥、域名)
确认提示

检查/安装 acme.sh

输入域名 (CF_Domain)
输入 API 密钥 (CF_GlobalKey)
输入注册邮箱 (CF_AccountEmail)

设置 CA 为 Let's Encrypt
导出环境变量CF_Key, CF_Email

签发通配符证书:
  acme.sh --issue --dns dns_cf -d ${domain} -d *.${domain} --force
  ↳ 使用 Cloudflare DNS 验证

创建证书目录 /root/cert/${domain}/

设置 reloadcmd同域名证书流程
安装证书(含 *.${domain} 通配符)
启用自动续期

询问是否为面板设置证书 → 同域名证书流程

特点:支持通配符证书 *.domain.com,不需要开放 80 端口(使用 DNS 验证)。


选项 21IP 限制管理Fail2ban

函数iplimit_main() — 子菜单入口

子菜单

 1. 安装 Fail2ban 并配置 IP 限制
 2. 修改封禁时长
 3. 解封所有人
 4. 封禁日志
 5. 封禁指定 IP 地址
 6. 解封指定 IP 地址
 7. 实时日志
 8. 服务状态
 9. 重启服务
10. 卸载 Fail2ban 和 IP 限制
 0. 返回主菜单

子选项 1安装 Fail2ban

函数install_iplimit()

检查 Fail2ban 是否已安装
  └─ 未安装 → 按发行版安装:
      Ubuntu ≥ 24: 额外安装 python3-pip + pyasynchat
      Debian ≥ 12: 额外安装 python3-systemd
      CentOS 7: 先装 epel-release

清除 jail 配置冲突iplimit_remove_conflicts
创建日志文件3xipl.log, 3xipl-banned.log
创建 jail 配置create_iplimit_jails
启动并启用 Fail2ban 服务

Jail 配置详情 (create_iplimit_jails)

# /etc/fail2ban/jail.d/3x-ipl.conf
[3x-ipl]
enabled=true
backend=auto
filter=3x-ipl
action=3x-ipl
logpath=/var/log/x-ui/3xipl.log
maxretry=2
findtime=32
bantime=30m          # 默认 30 分钟,可通过子选项 2 修改

过滤器:匹配 [LIMIT_IP] Email=... || Disconnecting OLD IP=... || Timestamp=... 格式的日志行。

动作:使用 iptables 封禁/解封 IP同时写入封禁日志文件。

子选项 2修改封禁时长

输入新的封禁时长(分钟)
重新生成 jail 配置 → 重启 Fail2ban

子选项 3解封所有人

fail2ban-client reload --restart --unban 3x-ipl
清空封禁日志文件

子选项 5/6手动封禁/解封 IP

输入 IP 地址 → 正则验证IPv4/IPv6
  fail2ban-client set 3x-ipl banip/unbanip "$ip"

子选项 10卸载

选项 1仅移除 IP 限制配置(保留 Fail2ban
  删除 filter.d/3x-ipl.conf, action.d/3x-ipl.conf, jail.d/3x-ipl.conf
  重启 Fail2ban

选项 2完全卸载
  删除 /etc/fail2ban
  停止服务
  按发行版卸载 fail2ban 包 + autoremove

选项 22防火墙管理

函数firewall_menu() — 子菜单入口(基于 UFW

子菜单

1. 安装防火墙
2. 端口列表 [带编号]
3. 开放端口
4. 删除列表中的端口
5. 启用防火墙
6. 禁用防火墙
7. 防火墙状态
0. 返回主菜单

子选项 1安装防火墙

函数install_firewall()

检查 ufw 是否安装 → 未安装则 apt-get install ufw
检查防火墙是否激活 → 未激活则:
  ufw allow ssh
  ufw allow http
  ufw allow https
  ufw allow 2053/tcp   ← webPort
  ufw allow 2096/tcp   ← subport
  ufw --force enable

子选项 3开放端口

函数open_ports()

输入端口(逗号分隔或范围,如 80,443,2053 或 400-500
验证输入格式
逐个处理:
  范围 → ufw allow start:end/tcp + ufw allow start:end/udp
  单端口 → ufw allow port
确认显示已开放的端口

子选项 4删除端口

函数delete_ports()

显示当前规则ufw status numbered
选择删除方式:
  1. 按规则编号删除 → ufw delete $number
  2. 按端口号删除 → ufw delete allow $port
确认显示已删除的端口

注意:原始代码中选项 4 有一个已知 bugfirewall_wall_menu 应为 firewall_menu),这会导致删除端口后不返回菜单。


选项 23SSH 端口转发管理

函数SSH_port_forwarding()

获取服务器公网 IP多 API 轮询)
读取当前面板设置:
  - webBasePath, port, listenIP, cert, key

判断状态:
  ├─ 已有证书+密钥 → "面板已配置 SSL安全" → 返回
  ├─ 无证书且 listenIP 为空或 0.0.0.0 → "面板不安全" 警告
  └─ listenIP 已设置且非 0.0.0.0 → 显示 SSH 转发命令

子菜单:
  1. 设置监听 IP
     ├─ 默认 127.0.0.1 或自定义
     ├─ x-ui setting -listenIP ${ip}
     └─ 显示 SSH 转发命令:
         ssh -L 2222:${listenIP}:${port} root@${server_ip}
         访问 http://localhost:2222${webBasePath}

  2. 清除监听 IP
     └─ x-ui setting -listenIP 0.0.0.0 → 重启

  0. 返回

用途:将面板绑定到 127.0.0.1,只能通过 SSH 隧道访问,提高安全性。


选项 24BBR 管理

函数bbr_menu() — 子菜单入口

子菜单

1. 启用 BBR
2. 禁用 BBR
0. 返回主菜单

启用 BBR

函数enable_bbr()

检查是否已启用tcp_congestion_control == bbr 且 default_qdisc 为 fq/cake
  ├─ 已启用 → 直接返回
  └─ 未启用 →
      有 /etc/sysctl.d/ →
        创建 /etc/sysctl.d/99-bbr-x-ui.conf
          net.core.default_qdisc = fq
          net.ipv4.tcp_congestion_control = bbr
        注释 sysctl.conf 中的旧设置
        sysctl --system
      无 /etc/sysctl.d/ →
        直接修改 /etc/sysctl.conf
        sysctl -p

验证tcp_congestion_control == bbr → "BBR 已成功启用"

特性:启用前会备份当前设置(写入注释行 #旧qdisc:旧拥塞控制),以便禁用时恢复。

禁用 BBR

函数disable_bbr()

检查是否已启用 → 未启用则返回

有 99-bbr-x-ui.conf →
  读取备份的旧设置
  恢复 net.core.default_qdisc 和 net.ipv4.tcp_congestion_control
  删除配置文件
  sysctl --system

无 99-bbr-x-ui.conf →
  将 sysctl.conf 中的 fq→pfifo_fast, bbr→cubic
  sysctl -p

验证tcp_congestion_control != bbr → "BBR 已成功替换为 CUBIC"

选项 25更新 Geo 文件

函数update_geo() — 子菜单入口

子菜单

1. Loyalsoldier (geoip.dat, geosite.dat)
2. chocolate4u (geoip_IR.dat, geosite_IR.dat)
3. runetfreedom (geoip_RU.dat, geosite_RU.dat)
4. 全部更新
0. 返回主菜单

数据源

选项 数据源 文件 用途
1 Loyalsoldier/v2ray-rules-dat geoip.dat, geosite.dat 通用规则
2 chocolate4u/Iran-v2ray-rules geoip_IR.dat, geosite_IR.dat 伊朗规则
3 runetfreedom/russia-v2ray-rules-dat geoip_RU.dat, geosite_RU.dat 俄罗斯规则
4 以上全部 全部 6 个文件 一键更新

下载逻辑 (update_geofiles)

每个文件:
  curl -fLRo ${xui_folder}/bin/${dat}.dat
       -z ${xui_folder}/bin/${dat}.dat    ← 仅在远程更新时下载
       https://github.com/${source}/releases/latest/download/${remote_file}.dat

-z 参数确保只有远程文件比本地新时才下载,节省带宽。

更新后自动重启面板以加载新规则。


选项 26网速测试 (Speedtest)

函数run_speedtest()

检查 speedtest 命令是否存在
  └─ 不存在 →
      有 snap → snap install speedtest
      无 snap → 按包管理器安装:
        dnf/yum → rpm 包源
        apt-get/apt → deb 包源
        curl 安装脚本 → 包管理器安装

执行 speedtest

子命令(命令行模式)

当脚本以参数调用时(如 x-ui start),跳过交互菜单直接执行:

子命令 对应菜单 附加行为
start 11 执行后不返回菜单
stop 12 执行后不返回菜单
restart 13 执行后不返回菜单
restart-xray 14 执行后不返回菜单
status 15 执行后不返回菜单
settings 10 执行后不返回菜单
enable 17 执行后不返回菜单
disable 18 执行后不返回菜单
log 16 执行后不返回菜单
banlog 4(限制) 执行后不返回菜单
update 2 执行后不返回菜单
legacy 4 执行后不返回菜单
install 1 使用 check_uninstall 前置检查
uninstall 5 执行后不返回菜单
update-all-geofiles 25-4 更新后自动重启
无效参数 显示用法帮助

所有子命令传递参数 0 给功能函数,使其执行后不调用 before_show_menu() 返回菜单。


调用关系总览

x-ui.sh
  │
  ├─ show_menu()
  │   ├─ show_status() → check_status() + show_enable_status() + show_xray_status()
  │   ├─ 0: exit
  │   ├─ 1: install() → install.sh → start()
  │   ├─ 2: update() → update.sh
  │   ├─ 3: update_menu() → 下载 x-ui.sh
  │   ├─ 4: legacy_version() → install.sh v$version
  │   ├─ 5: uninstall() → 停止服务 + 删除文件
  │   ├─ 6: reset_user() → x-ui setting -username/-password
  │   ├─ 7: reset_webbasepath() → x-ui setting -webBasePath
  │   ├─ 8: reset_config() → x-ui setting -reset
  │   ├─ 9: set_port() → x-ui setting -port
  │   ├─ 10: check_config() → x-ui setting -show + ssl_cert_issue_for_ip()
  │   ├─ 11: start() → systemctl/rc-service start
  │   ├─ 12: stop() → systemctl/rc-service stop
  │   ├─ 13: restart() → systemctl/rc-service restart
  │   ├─ 14: restart_xray() → systemctl reload
  │   ├─ 15: status() → systemctl/rc-service status
  │   ├─ 16: show_log() → journalctl/grep messages
  │   ├─ 17: enable() → systemctl/rc-update enable
  │   ├─ 18: disable() → systemctl/rc-update disable
  │   ├─ 19: ssl_cert_issue_main()
  │   │     ├─ 1: ssl_cert_issue() → acme.sh 域名证书
  │   │     ├─ 2: 吊销证书 → acme.sh --revoke
  │   │     ├─ 3: 强制续期 → acme.sh --renew --force
  │   │     ├─ 4: 查看已有域名
  │   │     ├─ 5: 设置面板证书路径
  │   │     └─ 6: ssl_cert_issue_for_ip() → acme.sh IP 短期证书
  │   ├─ 20: ssl_cert_issue_CF() → acme.sh Cloudflare DNS 通配符证书
  │   ├─ 21: iplimit_main()
  │   │     ├─ 1: install_iplimit() → install fail2ban + create_iplimit_jails()
  │   │     ├─ 2: 修改封禁时长
  │   │     ├─ 3: 解封所有人
  │   │     ├─ 4: show_banlog()
  │   │     ├─ 5/6: 手动封禁/解封 IP
  │   │     ├─ 7: tail -f fail2ban.log
  │   │     ├─ 8/9: 服务状态/重启
  │   │     └─ 10: remove_iplimit()
  │   ├─ 22: firewall_menu() → UFW 防火墙管理
  │   ├─ 23: SSH_port_forwarding() → 设置 listenIP 为 127.0.0.1
  │   ├─ 24: bbr_menu() → enable_bbr() / disable_bbr()
  │   ├─ 25: update_geo() → update_geofiles() → 下载 geoip/geosite .dat
  │   └─ 26: run_speedtest() → speedtest
  │
  └─ 子命令模式($# > 0
      └─ case $1 in "start"|"stop"|... → 对应函数 0

关键设计决策

  1. Alpine 兼容:所有服务管理操作都区分 Alpine (OpenRC) 和其他系统 (systemd),通过 $release 变量判断。

  2. 操作确认:危险操作(卸载、重置凭据等)默认为 "n",防止误操作。安全操作(更新等)默认为 "y"。

  3. 子命令模式:支持 x-ui start 等非交互式调用,传递参数 0 抑制 before_show_menu() 的回车等待。

  4. 状态前置检查:大多数菜单选项先调用 check_installcheck_uninstall,确保操作的前提条件满足。

  5. 等待机制start/stop/restart 后等待 2 秒再检查状态,给 systemd/init.d 足够时间完成操作。

  6. Geo 文件条件下载:使用 curl -z 参数,仅在远程文件比本地新时才下载,节省带宽和时间。

  7. BBR 备份恢复:启用 BBR 前将当前设置备份到注释行中,禁用时精确恢复原始值。

  8. Fail2ban jail 隔离IP 限制使用独立的 3x-ipl jail与系统默认 jail 分离,互不影响。