Files
ServerStack/.workbuddy/memory/2026-07-18.md
T
condor 679e0b4184 init
2026-07-24 18:54:53 +08:00

166 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)。