Skip to content

fix(rescue): headless 镜像按需装 xrdp + 状态判定与幂等修正 - #56

Merged
loficore merged 1 commit into
mainfrom
fix/rescue-vnc-on-headless
Oct 23, 2026
Merged

loficore merged 1 commit into
mainfrom
fix/rescue-vnc-on-headless

Conversation

@loficore

Copy link
Copy Markdown
Contributor

是什么

daedalus-host rescue 是 daedalus-atomic headless 镜像的一键救砖入口,三个子命令:enable-vnc / disable-vnc / status。本 PR 修它在真机上的三处缺陷 —— 修之前,enable-vnc 在 headless 镜像上必然失败。

问题

headless 镜像按设计不含 xrdp:files/scripts/77-xrdp.sh 在 VARIANT=headless 时第一行就 exit 0,连 epel-release 都不装。而 rescue 三个子命令全程假设 xrdp 已在 —— unmask xrdp、写 /etc/xrdp/startwm.sh、enable --now。

单测覆盖不到,因为 rescue_test.go 原本只测了「非 headless 主机上拒绝执行」和「状态字段非空」两个闸门,从不进入子命令主体。2026-10-22 在真机跑现役镜像,三处缺陷同时暴露:

$ daedalus-host rescue status
xrdp: disabled                  # 误导 —— 实际是「包根本没装」

$ daedalus-host rescue enable-vnc
rescue: 写 startwm.sh 失败: open /etc/xrdp/startwm.sh: no such file or directory
EXIT=1

$ daedalus-host rescue disable-vnc      # 在从未开过 VNC 的机器上
Failed to disable unit: Unit xrdp.service does not exist
EXIT=1

disable-vnc 那条尤其反直觉:「本就没开」正是它想达到的状态,却报非零退出,自动化脚本会误判。

改了什么

  • enable-vnc 按需装 xrdp。仓库来源与回退顺序跟 77-xrdp.sh 一致(EPEL → COPR mlampe/xrdp),不引入第三种来源 —— 运维不该需要记三套仓库配置。装完补 sesman.ini 的 depth=24:TigerVNC 1.15 的 Xvnc 不支持 32bpp,而 RDP 客户端默认 32bpp,不改会 X server failed to start → VNC 黑屏。构建期 77-xrdp.sh 已踩过此坑。
  • LoadState=not-found 映射为 not-installed,不再报 disabled。顺带修掉 probeXrdpUnitState 首部注释与实现长期矛盾的问题(注释写「unit 不存在 → unknown」,代码返回 disabled)。
  • disable-vnc 幂等:unit 缺失即视为已达目标;真错误(非 unit-missing 文案)仍照旧非零退出。
  • status 在 not-installed 时补一行 enable-vnc 指引。

装没装的判据是 stat /usr/sbin/xrdp,不是 systemctl 的 LoadState。 这是本 PR 开发过程中真机复现的第二轮缺陷:disable-vnc 跑过一次 mask 之后,systemctl show xrdp 报 masked 而非 not-found(mask 的语义就是「不论 unit 存不存在一律拦」),第一版拿 unit 状态当安装标志,于是跳过安装、紧接着写 startwm.sh 仍然 ENOENT。单测没抓到,因为测试直接 stub 了 state。

测试

新增 9 个,其中 4 个表驱动直接钉住上述缺陷。外部命令统一收敛到单一出口 execOut(firewall 调用也一并收进去,否则在装了 firewalld 的开发机上跑测试会真改系统状态),测试替换它即可在没装 systemd / dnf 的 CI 上驱动全流程。

做了变异验证 —— 逐个把修正还原为原始行为,确认对应测试会红:

变异 结果
not-found 映回 disabled TestMapXrdpUnitState FAIL
去掉按需安装 TestRescue_EnableVnc_InstallsXrdpWhenNotInstalled FAIL
去掉 disable 幂等 TestRescue_DisableVnc_IdempotentWhenNotInstalled FAIL

go test -count=1 ./... 全绿。

真机复验

故意先 disable-vnc(制造 LoadState=masked 而包不存在)再 enable-vnc:

rescue: xrdp 未安装(headless 镜像不含 RDP 包),正在按需安装 …
rescue: EPEL 无 xrdp,改走 COPR mlampe/xrdp
rescue: xrdp 已从 COPR 装上
xrdp: enabled

$ rpm -q xrdp                  xrdp-0.10.6.1-2.el10.x86_64
$ systemctl is-enabled xrdp   enabled
$ cat /etc/xrdp/startwm.sh    exec xterm

disable-vnc 幂等、status 报 not-installed 也各自单独复验过。

遗留

装包要出网。机器若正因为断网而砖,enable-vnc 会失败 —— 此时 stderr 会指向串口控制台与 sshd 两条不依赖 xrdp 的路径,这两条已在上轮真机验证中确认可用。

headless 变体的守护脚本目前无 CI 门禁,见 #55。本 PR 只修 daedalus-core 侧,almalinux-bootc 侧的 live 探测修复在那个仓的对应 PR。

daedalus-atomic headless 镜像按设计不含 xrdp(files/scripts/77-xrdp.sh 在
VARIANT=headless 时第一行就 exit 0),而 rescue 三子命令全程假设 xrdp 已在。
真机跑 ghcr.io/daedalusys/daedalus-os:latest 后确认三处缺陷,均导致救砖
路径在真机上不可用。

真机复现(2026-10-22,daedalus-os:latest,created 2026-10-21):

  $ daedalus-host rescue status
  xrdp: disabled            <- 误导:实际是「包根本没装」
  $ daedalus-host rescue enable-vnc
  rescue: 写 startwm.sh 失败: open /etc/xrdp/startwm.sh: no such file or directory
  EXIT=1
  $ daedalus-host rescue disable-vnc      # 在从未开过 VNC 的机器上
  Failed to disable unit: Unit xrdp.service does not exist
  EXIT=1

修正:

- enable-vnc 按需安装 xrdp:EPEL → COPR mlampe/xrdp,与 77-xrdp.sh 同一套仓库
  来源与回退顺序,不引入第三种。装完补 sesman.ini 的 depth=24(TigerVNC 1.15
  不支持 32bpp,不改会 VNC 黑屏;构建期 77-xrdp.sh 已踩过此坑)。
- 装没装的判据改为 stat /usr/sbin/xrdp,不取 systemctl 的 LoadState。disable-vnc
  跑过一次 mask 后 LoadState 会变成 masked 而非 not-found,拿它当安装标志会误判
  「装过了」并跳过安装 —— 这是本 PR 开发过程中真机复现的第二轮缺陷。
- mapXrdpUnitState 把 LoadState=not-found 映射为 not-installed,不再报 disabled。
- disable-vnc 幂等:unit 缺失即视为已达目标,不非零退出;真错误仍照旧失败。
- status 在 not-installed 时补一行 enable-vnc 指引。

测试:新增 9 个,其中 4 个表驱动直接钉住上述缺陷。已做变异验证 —— 逐个把修正
还原为原始行为,对应测试均失败。全仓 go test -count=1 通过。

真机复验(先 mask 再 enable,LoadState=masked 而包不存在):

  rescue: xrdp 未安装(headless 镜像不含 RDP 包),正在按需安装 …
  rescue: EPEL 无 xrdp,改走 COPR mlampe/xrdp
  rescue: xrdp 已从 COPR 装上
  xrdp: enabled
  $ rpm -q xrdp                  xrdp-0.10.6.1-2.el10.x86_64
  $ systemctl is-enabled xrdp   enabled
  $ cat /etc/xrdp/startwm.sh    exec xterm
@loficore
loficore merged commit c54a820 into main Oct 23, 2026
6 checks passed
@loficore
loficore deleted the fix/rescue-vnc-on-headless branch October 23, 2026 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant