This commit is contained in:
condor
2026-07-24 18:54:53 +08:00
parent 43c2a411b9
commit 679e0b4184
128 changed files with 13855 additions and 1 deletions
+165
View File
@@ -0,0 +1,165 @@
# 2026-07-18
## ServerStack: 修复 Ubuntu 依赖安装的 libcurl 冲突
**问题**:在 Ubuntu 22.04 上跑 `installDepsUbuntu` 时出现
- 图片 1: `libcurl4-gnutls-dev``libcurl4-openssl-dev` 互相 Conflicts,导致
`E: Unable to correct problems, you have held broken packages`,整批依赖装不下去。
- 图片 2: 大量老包被 `filter_pkglist` 跳过(`libpng12-0/-dev``libpng3`
`libidn11``libcloog-ppl1``sysv-rc``libjpeg62-turbo-dev`),虽然不报错,
但每次都刷一堆 `Skip unavailable package: ...` 噪音。
**根因**`lib/check_sw.sh``installDepsUbuntu`line 119)的 pkgList
同时列了 `libcurl4-gnutls-dev``libcurl4-openssl-dev` 这两个互斥的 `-dev` 包。
注释里说"Modern Debian/Ubuntu removed several legacy package names",但实际
pkgList 自身并没有清理这些老包。
**修复**`E:\workbuddy\ServerStack\lib\check_sw.sh`,仅改 Ubuntu 列表 line 119):
- 删掉 `libcurl4-gnutls-dev`(保留 `libcurl3-gnutls` 这个 runtime)。
依据:`modules/php/php-7.4.sh``php-8.0.sh``php-8.1.sh` 全部用
`libcurl4-openssl-dev`,没有任何地方用 gnutls dev。
- 顺手清理在新版 Ubuntu 上永远被 filter 跳过的死链包:
`libjpeg62-turbo-dev``libpng12-0/-dev``libpng3``libidn11`
`libcloog-ppl1``sysv-rc``libidn11-dev` 保留(仍可用),Debian 分支的
列表不动(不同发行版软件源不同)。
- 加了一段说明注释,避免后人重新加回 `libcurl4-gnutls-dev`
**验证**`bash -n` 通过;图片 1 的冲突不会再出现,图片 2 的 Skip 噪音也基本清零。
## 补充:用户反馈同样的报错仍在出现
用户第二轮贴出**完全相同**的报错文本(含 `7.81.0-1ubuntu1.25` 版本号和
`No VM guests are running outdated hypervisor (qemu)` 这条云 VM 特征消息)。
排查结论:
- 本地 `lib/check_sw.sh` 的 Ubuntu 列表(line 141)已经是干净的,没有
`libcurl4-gnutls-dev`
- `backup/``runtime/` 都是空目录,全项目只有一份 `check_sw.sh`,没有其它副本。
- 报错来自**远程 Ubuntu 22.04 服务器**上跑的旧版脚本,本地修改还没同步过去。
### 加防御层(`filter_pkglist()` 末尾,line 33-47
为了即使旧版 pkgList 被部署上去也不炸,在 `filter_pkglist()` 末尾加了一段
互斥冲突消解:检测列表里同时有 `libcurl4-gnutls-dev``libcurl4-openssl-dev`
时,自动 sed 摘掉 gnutls dev 版,保留 openssl 版(PHP 各模块用的就是它),
`libcurl3-gnutls` runtime 不动。
隔离测试通过:`libcurl3-gnutls` 保留 / `libcurl4-openssl-dev` 保留 /
`libcurl4-gnutls-dev` 被移除。`bash -n` 语法通过。
### 给用户的行动项
需要把更新后的 `lib/check_sw.sh` 重新同步到服务器(rsync/scp/git pull 等),
然后重跑安装。同步后两层防护都会生效:
1. Ubuntu 列表源头已无 `libcurl4-gnutls-dev`(也不会再有 Skip 噪音)。
2. 即便将来有人把互斥包加回去,`filter_pkglist` 会自动摘掉。
## 第三轮:修复"卡很久"的黑屏问题
用户反馈"在运行到此处时会卡很久"。分析 `install_pkgs()` 的卡顿来源:
1. **批量 apt-get 遇冲突时静默求解**apt 的依赖求解器遇到 `libcurl4-gnutls-dev`
vs `libcurl4-openssl-dev` 互斥时,会花 30s~2min 尝试各种组合才放弃,期间
**无任何输出**,看起来像冻住。
2. **逐包回退循环全静默**:批量失败后循环 ~60 个包,每个 `apt-get install` 输出
全 redirect 到 `/dev/null`,用户看到几分钟黑屏。
### 改动(`lib/check_sw.sh` 的 `install_pkgs()`line 74-109
- 批量安装前再补一道冲突消解(防御纵深,防 filter_pkglist 被绕过或 pkgList
被中间修改)。
- 回退循环改成可见进度:每个包先 `printf` 包名(cyan,左对齐 40 列),再装,
装完打 `OK`(绿)/`FAILED`(红)。屏幕永不空白。
- 颜色变量复用 `lib/color.sh` 里已定义的 `CMSG/CSUCCESS/CFAILURE/CEND`
- `cat -v` 验证对齐和转义正确,`bash -n` 语法通过。
### 三层防护总览(都已在本地 `lib/check_sw.sh`
1. `installDepsUbuntu` 的 pkgList 源头已删 `libcurl4-gnutls-dev` + 死链包。
2. `filter_pkglist()` 末尾自动消解 libcurl dev 互斥冲突。
3. `install_pkgs()` 开头再消解一次 + 回退循环可见进度。
**用户必须做的**:把 `lib/check_sw.sh` 同步到服务器再重跑。当前服务器上跑的
还是旧版,所以三轮都看到同样的报错。
## 第四轮:审视整个项目,杜绝静默安装
用户要求"不要静默安装, 要有相关提示"。全项目扫描结论:
### 扫描发现
- 大多数 `make -j` / `./configure` **没有**被 `/dev/null` 吞输出(调用方
`run_install()``Install_X | tee` 会显示并写日志),只是**缺起始提示**。
- 唯一真正把安装输出吞掉的只有 `lib/check_sw.sh` 逐包回退的
`apt-get ... >/dev/null 2>&1`(第三轮已改成可见进度,本轮再改成完全不吞)。
- 下载环节 `lib/download.sh``Download_src()``wget -c`(无 `-q`),带进度,OK。
- 所有模块安装统一经 `lib/loader.sh``run_install()`,是加统一提示的**单点**。
### 改动清单(7 个文件,`bash -n` 全通过)
1. `lib/loader.sh` `run_install()`:加 `>> Installing: <func>` 横幅(带 module 路径)。
改这一处覆盖全部 47 个模块 + 主流程。
2. `lib/check_sw.sh` `install_pkgs()` 回退循环:去掉 `>/dev/null`,每个包打印
"Installing X ..." → "X installed OK / install FAILED"apt 下载进度可见。
3. `lib/openssl.sh` `Install_openSSL()`:开头加 ">> Installing: openSSL ver"。
4. `modules/web/jemalloc.sh` `Install_Jemalloc()`:开头加 ">> Installing: jemalloc ver"。
5. `lib/check_sw.sh` `installDepsBySrc()`ICU):开头加 ">> Installing: ICU ver"。
6. `core/environment.sh` `prepare_install()``${PM} -y install wget gcc curl python`
加提示 + `tee` 写日志(与上方 apt-get update 一致)。
7. `core/os/init_Ubuntu.sh` / `init_Debian.sh`iptables 安装两处 `apt-get` 加提示。
### 验证
- `grep 'apt-get.*install.*>/dev/null'` 全项目无匹配 → 再无静默 apt 安装。
- 编译步骤输出仍可经 `| tee` 看到并落日志。
- 收尾仍要提醒:所有改动需 `rsync`/`git pull` 到服务器才会生效。
## ServerStack: apt-get 依赖安装改为静默(-y) + 写日志
**需求变更**:上一轮把逐包回退改成屏幕逐行可见;这轮用户改口要
「apt-get 静默安装(`-y`) + 输出安装日志」。
**改动**`lib/check_sw.sh``install_pkgs()`):
- 统一 `export DEBIAN_FRONTEND=noninteractive`,apt 完全非交互(不再卡 debconf 提示)。
- 批量安装:`apt-get --no-install-recommends -y install ${pkgList} >> runtime/install.log 2>&1`
屏幕只打印 `Installing dependency packages (... -> install.log)` 起始行 +
成功后 `All dependency packages installed successfully.`
- 逐包回退:每个包同样 `apt-get -y ... >> install.log 2>&1`,屏幕只保留一行
` -> <pkg> ... OK/FAILED`printf 左对齐 40 列,OK 绿/FAILED 红)。
- 日志路径 `local _log="${oneinstack_dir:-.}/runtime/install.log"`,与外层
`installDepsUbuntu 2>&1 | tee` 同一文件;apt 详细输出直接追加、屏幕状态经 tee 落一份,无重复。
- 同步更新函数顶部注释,去掉旧的 /dev/null 描述。`bash -n` 通过。
**设计要点**:屏幕保留简洁状态(可读、不黑屏),完整 apt 输出进 install.log(可 grep 排障)。
## 第五轮:修复安装摘要 URL 显示 http:/// IPADDR 为空)
**根因**`IPADDR``core/environment.sh``prepare_install()``./lib/py/get_ipaddr.py` 获取,
该脚本靠 shebang `#!/usr/bin/env python` 启动;Ubuntu 22.04+ 只有 `python3``python` 命令,
且 base-tools 装的是不存在的 `python` 包、symlink 补救被 `~/.oneinstack` 判断限制,
导致脚本静默失败 → 标准输出空 → `IPADDR` 空 → 摘要 URL 变成 `http:///ocp.php` 等。
**修复**(仅 `environment.sh` + `bin/upgrade.sh``bash -n` 均通过):
1. 新增纯 shell 函数 `get_local_ipaddr()`environment.sh),按
`ip route get src``hostname -I``ip -o -4 addr show scope global``127.0.0.1` 回退,**不依赖 python**。
2. `IPADDR=$(./lib/py/get_ipaddr.py)` 改为 `IPADDR=$(get_local_ipaddr)`
3. base-tools 安装 `python``python3``/usr/bin/python` 软链改**无条件**创建,
让 get_public_ipaddr.py / get_ipaddr_state.py 也能跑。
4. `bin/upgrade.sh` 独立入口同样加无条件 `python` 软链兜底。
**验证**mock 命令测 `get_local_ipaddr` 三种场景均正确(有路由取 src / 无路由回退 hostname / 全无回退 127.0.0.1)。
**注意**:改动仍在本地,需同步到服务器后重装/重跑 install 生效。
## 第五轮补充:VPC/私网场景让摘要 URL 改用公网 IP
用户指出服务器是 **VPC 网络**。澄清:空 IP bug 与 VPC 无关(是 python 缺失);但 VPC 决定了
"显示哪个 IP"——`ip route get` 在 VPC 取到的是**私网 RFC1918 地址**,从外部经公网 IP/EIP 访问时
私网 URL 打不开。
**补充改动**`core/environment.sh`):
1. 取 IP 顺序改为先 `PUBLIC_IPADDR=$(get_public_ipaddr.py)``IPADDR=$(get_local_ipaddr)`
让本地检测函数能引用已解析的公网 IP。
2. `get_local_ipaddr()` 末尾加 case`10.* / 172.16-31.* / 192.168.*` 私网段且
`PUBLIC_IPADDR` 非空时,改用公网 IP;公网取不到则安全保留私网 IP。
**验证**:mock 四场景全过(VPC私网+公网→公网 / VPC私网+公网失败→私网 / 经典VM公网→公网 / 纯内网192.168+失败→192.168)。