mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-07 13:44:24 +00:00
- 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
13 KiB
13 KiB
install.sh 问题评估与分级
说明
本文对 install.sh 及其直接依赖的服务文件进行静态审查,输出逻辑问题、潜在 Bug 与风险分级。
- 审查对象:
install.sh、x-ui.service.arch、x-ui.service.debian、x-ui.service.rhel、x-ui.rc - 审查方式:静态阅读 +
bash -n install.sh - 结论范围:以脚本逻辑为主,不包含联网下载内容真实性、外部服务可用性与目标主机现场状态
分级标准
| 级别 | 含义 |
|---|---|
| P0 / 致命 | 高概率导致安装结果错误、服务不可用、错误安全结论、数据错写或危险操作 |
| P1 / 高 | 在常见环境下容易触发,导致功能失败、行为不一致或明显错误 |
| P2 / 中 | 不是每次触发,但会造成兼容性、稳健性、可维护性或边界行为问题 |
| P3 / 低 | 风险较低,主要是误导、死代码、风格不一致或隐含维护成本 |
总览
| 级别 | 数量 | 重点 |
|---|---|---|
| P0 / 致命 | 8 | 端口检测失效、SSL 失败仍报成功、MariaDB 新装数据错位、目录漂移 |
| P1 / 高 | 12 | 自定义目录不完整支持、安装失败继续、弱口令、服务路径错误 |
| P2 / 中 | 18 | 输入校验不足、平台兼容性差、下载/解析脆弱、引号缺失 |
| P3 / 低 | 8 | 死代码、注释偏差、提示文案不准确、维护性问题 |
P0 / 致命
| ID | 位置 | 问题 | 影响 | 建议 |
|---|---|---|---|---|
| P0-01 | install.sh:63, install.sh:67 |
is_port_in_use() 中 awk ... END {exit 1} 覆盖前面的成功退出码,导致 ss/netstat 分支几乎总返回“端口未占用” |
端口冲突检测失效,ACME 独立监听端口选择可能错误,安装过程可能与现有服务抢端口 | 改为纯 grep/ss 判断,或让 awk 使用状态变量并在 END 中按变量返回 |
| P0-02 | install.sh:955, install.sh:966, install.sh:969 |
SSL 配置函数失败后,安装摘要仍打印 HTTPS 地址和“SSL 已启用并配置” | 用户被误导为已启用 HTTPS,可能错误暴露面板 | 必须检查 prompt_and_setup_ssl 返回值,失败时终止安装摘要或明确显示失败 |
| P0-03 | install.sh:587, install.sh:589 |
ssl_cert_issue() 返回值未检查,且用 `acme.sh --list |
tail -1` 取最后一张证书推断本次签发结果 | 可能把旧证书/无关证书当成本次成功结果写入面板域名 |
| P0-04 | install.sh:859, install.sh:863, install.sh:867, install.sh:869 |
提示称“留空或 rd 自动生成”,实际用户名/密码默认是 admin/admin |
新装面板默认弱口令,安全风险极高 | 留空时应真正随机生成密码,用户名至少提示确认 |
| P0-05 | install.sh:890, install.sh:914-920, install.sh:991 |
新装流程先按默认 SQLite 写面板配置,再切换 dbType=mariadb,但没有执行 SQLite→MariaDB 数据迁移 |
最终服务连接 MariaDB 后,用户刚设置的账号/端口等可能不在实际使用库里 | 先确定数据库类型,再初始化与写配置;若从 SQLite 切 MariaDB,必须执行显式迁移 |
| P0-06 | install.sh:157, install.sh:1106, install.sh:1135-1176 |
install_acme() 进入家目录后不恢复;config_after_install() 里一旦调用它,会污染后续当前工作目录 |
可能找不到解压包中的 service 文件,导致安装行为与预期不一致 | 在函数内保存并恢复目录,或完全使用绝对路径 |
| P0-07 | x-ui.service.arch:10-11, install.sh:11, install.sh:1135-1159 |
Arch 服务文件硬编码 /usr/lib/x-ui,而脚本默认安装到 /usr/local/x-ui |
Arch 系统默认安装后服务大概率无法启动 | 安装时模板渲染 ExecStart/WorkingDirectory,不要硬编码 |
| P0-08 | install.sh:1078-1084 |
依赖环境变量的目录删除缺乏安全防护,直接 rm -rf ${xui_folder}/ |
若 XUI_MAIN_FOLDER 被误设,可能删除错误目录 |
删除前校验路径非空、非根目录、符合预期前缀,并统一加引号 |
P1 / 高
| ID | 位置 | 问题 | 影响 | 建议 |
|---|---|---|---|---|
| P1-01 | install.sh:1041 |
用 ${xui_folder%/x-ui} 推导工作目录,隐式假设安装目录以 /x-ui 结尾 |
自定义目录时下载/解压位置可能错误 | 单独定义工作目录,不要从安装目录字符串裁剪推导 |
| P1-02 | install.sh:1088-1091 |
解压与 cd x-ui 不检查失败 |
后续 chmod、复制 service、配置命令可能在错误目录执行 | 每一步关键文件操作都要显式检查退出码 |
| P1-03 | install.sh:1106 |
config_after_install 失败后仍继续安装 service 并启动 |
配置失败被掩盖,最终系统状态不可预测 | 将其纳入主流程错误链,失败立即退出 |
| P1-04 | install.sh:76-104, install.sh:1232-1234 |
install_base() 失败后脚本仍继续执行 |
缺依赖状态下继续安装,错误位置后移且更难排查 | 主流程必须检查基础依赖安装结果 |
| P1-05 | install.sh:1071, install.sh:1176-1188 |
指定版本安装时,管理脚本和 fallback service 仍从 main 分支下载 |
脚本/服务文件与二进制版本不匹配,可能出现不兼容 | 统一按所选 tag 下载同版本配套文件 |
| P1-06 | install.sh:1048, install.sh:1065, install.sh:1071, install.sh:1180-1186 |
多处强制 curl -4 |
IPv6-only 主机无法安装或更新 | 优先正常双栈请求,失败后再回退到 -4 |
| P1-07 | install.sh:981-988 |
已有安装路径中,只要 cert 字段非空就认定已配置 SSL,并打印 HTTPS 地址 |
可能在没有有效证书/私钥时误导用户 | 同时校验 cert、key、文件存在性和可读性 |
| P1-08 | install.sh:429-435 |
证书重复判断只比较 acme.sh --list 最后一条记录 |
已有当前域名证书时仍可能重复签发 | 遍历列表精确匹配域名,或直接查询目标证书目录 |
| P1-09 | install.sh:384-386 |
IP 证书流程中,x-ui cert 失败只告警不失败,仍打印“安装并配置成功” |
证书文件虽存在,但面板未实际启用证书 | 写入路径失败应判定整体失败 |
| P1-10 | install.sh:611-618, install.sh:623-625 |
IP 证书模式停止面板后,失败路径没有统一保证服务恢复 | 安装中断后面板可能保持停止状态 | 使用 trap 或统一清理/恢复逻辑 |
| P1-11 | install.sh:1137-1203, x-ui.service.debian:10-11, x-ui.service.rhel:10-11, x-ui.rc:3, x-ui.rc:12 |
虽允许 XUI_MAIN_FOLDER 覆盖,但 service/init 模板大量硬编码 /usr/local/x-ui |
自定义安装目录时服务启动失败 | 安装时根据变量生成 service/init 文件 |
| P1-12 | install.sh:994-1015 |
用 tr/grep/sed 解析 GitHub Releases JSON,逻辑脆弱 |
API 结构变化、字段顺序变化、错误响应时容易取错版本 | 使用 jq,或服务端返回最小化 API 请求并严格校验 JSON |
P2 / 中
| ID | 位置 | 问题 | 影响 | 建议 |
|---|---|---|---|---|
| P2-01 | install.sh:158 |
`curl ... | sh缺少pipefail`,下载失败时可能误报 acme 安装成功 |
安装状态不可信 |
| P2-02 | install.sh:177, install.sh:249, install.sh:396, install.sh:732 |
用 command -v ~/.acme.sh/acme.sh 检查路径式命令,可用但不规范 |
兼容性与可读性较差 | 直接使用 [ -x ~/.acme.sh/acme.sh ] |
| P2-03 | install.sh:193, install.sh:321, install.sh:463, install.sh:743 |
设置默认 CA 的命令结果多数未检查 | 前置动作失败时后续错误定位困难 | 对关键前置步骤逐一校验 |
| P2-04 | install.sh:263-266, install.sh:46-50 |
IPv4/IPv6 校验过于宽松:IPv4 不校验每段范围,IPv6 只看是否含 : |
非法地址可能进入证书流程 | 使用更严格的地址校验函数 |
| P2-05 | install.sh:451-455 |
手动 SSL 端口输入为空时不会自然采用默认值,而是走“无效输入”分支 | 交互体验与提示不一致 | 先 WebPort="${WebPort:-80}" 再校验 |
| P2-06 | install.sh:452 |
手动 SSL 端口校验未先判断是否纯数字 | 异常输入由 shell 算术比较隐式处理,不稳健 | 先正则校验再做范围比较 |
| P2-07 | install.sh:881-888 |
面板端口输入没有有效校验,也不检测占用 | 可能写入非法端口或冲突端口 | 校验数字范围并复用端口占用检测 |
| P2-08 | install.sh:886 |
随机端口不检查是否已被占用 | 启动服务时可能冲突 | 生成后循环检测空闲端口 |
| P2-09 | install.sh:890-897 |
只验证端口写入成功,不验证用户名、密码、webBasePath 是否确实写入 |
配置失败可能部分隐藏 | 对关键配置项逐项校验 |
| P2-10 | install.sh:899-920 |
MariaDB 连接信息读取与写入缺少完整校验,账号/密码/库名可以为空 | 后续数据库初始化失败 | 按数据库类型做必填校验与连通性预检查 |
| P2-11 | install.sh:929-945 |
worker 仅校验 dbType=mariadb,不校验 MariaDB 是否可连接 |
worker 模式可能被写入无效配置 | 在设置前做配置与连接校验 |
| P2-12 | install.sh:846-855, install.sh:955 |
获取公网 IP 失败后不提示手动输入,IP 证书默认路径会直接失败 | 默认交互路径容易走向失败 | IP 获取失败时要求用户手输或默认跳过 IP 证书 |
| P2-13 | install.sh:707-729 |
Cloudflare 域名未用 is_domain 校验,API Key 非静默输入 |
容易误输,且敏感信息暴露在终端 | 域名校验 + read -rsp 输入密钥 |
| P2-14 | install.sh:751-752 |
Cloudflare 凭证 export 后未清理 |
后续子进程可见环境变量 | 完成后 unset CF_Key CF_Email |
| P2-15 | install.sh:491 |
允许用户输入任意 reloadcmd,续期时将以高权限执行 |
误操作或恶意输入可能造成风险 | 至少明确安全提示,并对常见场景提供模板而非完全任意命令 |
| P2-16 | install.sh:91-92 |
Arch 依赖安装执行两次 pacman -Syu,且第一次无 --noconfirm |
交互阻塞、重复更新、耗时增加 | 合并为一次清晰的安装命令 |
| P2-17 | install.sh:1088-1100 |
ARM 分支先重命名 bin/xray-linux-$(arch),后面又对原文件名 chmod |
可能输出错误信息并污染日志 | 重命名后按最终文件名处理权限 |
| P2-18 | install.sh:1048, install.sh:1065, install.sh:1071 等多处 |
路径、URL、命令参数大量未加引号 | 自定义目录、异常字符或空格路径下行为不稳定 | 统一为变量引用加引号 |
P3 / 低
| ID | 位置 | 问题 | 影响 | 建议 |
|---|---|---|---|---|
| P3-01 | install.sh:9 |
cur_dir 未使用 |
增加噪音 | 删除死代码 |
| P3-02 | install.sh:168-236 |
setup_ssl_certificate() 未被调用,且参数 server_ip、existing_port、existing_webBasePath 未使用 |
阅读成本高,容易误导维护者 | 删除死函数或接入统一 SSL 流程 |
| P3-03 | install.sh:52-54 |
is_ip() 未被调用 |
维护噪音 | 删除或实际复用 |
| P3-04 | install.sh:39 |
不支持架构时删除当前 install.sh |
行为危险且无必要 | 直接报错退出,不做文件删除 |
| P3-05 | install.sh:578 |
注释“非 1、3、4 默认为 2”表述不完整 | 容易造成维护误解 | 注释改为“除 1/3/4 外均视为 2” |
| P3-06 | install.sh:827-832 |
“全新安装”的判定只看两个文件是否存在,注释与语义不够精确 | 可读性一般 | 把注释改成“基于配置/数据库文件存在性判断” |
| P3-07 | install.sh:1044 |
[ $# == 0 ] 属于 bash 风格写法,可运行但不如 -eq 清晰 |
风格一致性较差 | 改用 [ $# -eq 0 ] |
| P3-08 | install.sh:1234 |
install_x-ui $1 未加引号 |
边界输入下会参数拆分 | 改为 install_x-ui "$1" |
优先修复建议
建议按以下顺序修复:
- 先修
P0-01、P0-02、P0-05、P0-06、P0-07 - 再修
P1-01、P1-03、P1-05、P1-11 - 然后补齐输入校验、错误处理和引号问题
- 最后清理死代码、注释和交互文案
建议的验收点
- 端口占用检测在
ss、netstat、lsof三种环境下都能正确判定 - SSL 任一路径失败时,最终摘要不再显示成功状态
- SQLite / MariaDB 两种新装流程都能得到一致且可登录的实际配置
- 自定义
XUI_MAIN_FOLDER后,服务文件仍能正确启动 - Arch、Debian/RHEL、Alpine 三类服务安装路径与执行路径一致
- 在公网 IP 获取失败、80 端口不可用、证书签发失败等场景下,脚本能给出准确结果而非伪成功