一句话
不是单一故障,是「nix-ld 缺 Electron 运行库(已在世代层独立证实)」+「gateway 僵尸态重启循环」+「drkonqi 自身崩溃制造噪音」叠加。与克隆操作无因果关系——崩溃比克隆结束晚 26 分钟。而报告漏掉了最要紧的一条:克隆到盘1 的配置停在修复之前,盘1 启动后会原样复发。
时间线(实测,全部可追溯)
| 时刻 | 事件 | 证据来源 |
|---|
| 13:31 – 13:43:57 | 克隆盘2→盘1,rsync 29.7 GB / 2,240,069 文件 | clone-disk1.log |
| 13:39:13 | 盘1 生成 gen48 | 盘1 loader/entries |
| 14:09:46 / 14:09:55 / 14:13:49 / 14:14:11 / 14:22:13 | Hermes 二进制 SIGILL ×5 | coredumpctl list |
| 14:22:17 | drkonqi 列 coredump,自身也 SIGABRT | 用户 journal |
| 14:22 – 14:26 | gateway「already owns this host」循环,restart counter → 29 | 用户 journal |
| 14:25:04 | configuration.nix 被改(补 nix-ld 库) | 文件 mtime |
| 14:25:58 | gen47 = fix-hermes-desktop-black-after-clone-nixos | profile link |
| 14:29:38 | 重启 | /proc/uptime 反推 |
| 14:32:32 | desktop 启动,其后 0 崩溃 | ps + journal |
逐条裁决:报告的 5 层根因
| 报告的判定 | 裁决 | 实测依据 |
|---|
层1:TMPDIR 残留 Windows 路径 C:\Users\cat\.hermes\tmp | 方向对,位置判错,且与本次崩溃无关 | ~/.hermes/.env:530 与 profiles/nixos-u533b-u751f/.env:526 都已是 /home/cat/.hermes/tmp(mtime 分别 10-06、10-08,本次 sed 没动过它们)。Windows 路径只残留在 profiles/win10-u533b-u751f/.env:526。崩溃的 default profile 读的不是那个文件 → 该层不成立为本次病因,但是真隐患(切到 win10 profile 就会踩,会在 $HOME 下建出 ~/C:\Users\... 垃圾目录) |
| 层2:node-pty 缺 C++ 编译链 | 事实成立,归因不成立 | gcc/gnumake/python3/pkg-config 确在 configuration.nix 第 180 行;但 desktop 跑的是预编译包 ~/.hermes/hermes-agent/apps/desktop/release/linux-unpacked/Hermes(198 MB,mtime 10-06 22:56),不跑 npm ci → 与黑屏无因果 |
| 层3:nix-ld 缺 Electron 运行库 → SIGILL | 采信(已独立硬证实) | 逐世代对比 <system>/sw/share/nix-ld/lib:gen45/gen46 = 437 个库,缺 libGLX_mesa / libfontconfig / libgdk_pixbuf / libpulse;gen47 起 = 525 个,四个全在。这是版本层面可复现的证据,非推测 |
| 层4:GPU 子进程初始化失败 | 现象采信,机制表述需修正 | Chromium/Electron 里的 SIGILL 不是「跳到非法指令」,而是 IMMEDIATE_CRASH()(x86 的 ud2)——代码主动触发的 CHECK / LOG(FATAL) 自杀。正确说法是「某处致命校验失败」,缺库或 GPU 初始化失败只是可能的触发条件之一;崩溃位于 --type=zygote,与「GPU 子进程」同类但不等价 |
| 层5:sandbox fallback 残留 + transient unit 残留 | 部分采信 / 部分不可证 | transient unit 确实失败且至今未清:drkonqi-coredump-launcher@… ×3 仍 failed;windows-sandbox-fallback.json 当前是 {"state":"ok"},当时的旧值已无法回溯,此条不构成证据 |
| 「gateway 层有僵尸锁」 | 采信(日志实锤) | A gateway already owns this host … PID 1101 (launched by profile 'default'; serves: not published yet (its control socket has not answered)) 每 ~11 秒一次,restart counter is at 27…29;本次开机后 0 次 |
| 归因「因克隆而起」(你的重建标签写的是 after-clone-nixos) | 驳回 | 克隆 13:43:57 结束,崩溃 14:09:46 起,相隔 26 分钟;且崩溃所处的 gen46 建于 12:32(早于克隆)。无因果证据。真实触发点已不可考——desktop 的 stderr 走了终端、没进 journal |
| 「libglvnd 不能单独工作」/「drkonqi 崩溃是噪音」 | 采信 | libglvnd 只是 dispatcher;实测 drkonqi-coredump-launcher 自身 SIGABRT ×6 |
报告漏掉的(本次新增,最要紧)
- 盘1 停在修复之前,启动后会原样复发。 克隆同步时刻 13:43:57,nix-ld 修复写入 14:25:04 → 盘1 的
/etc/nixos/configuration.nix 及其 gen48 不含那四个库,库数会是 437 而非 525。追平之前不要以主力身份启动它。 - 启动窗口内时钟错了 8 小时。
date/timedatectl = 14:37 CST(RTC 06:37 UTC,正确),但本次开机的 journal 与 who -b 都记成 22:29/22:30,systemd 甚至显示 since 22:29:45; 7h left。事后靠日志复盘会踩这个坑。 - 残留 Windows 路径的确切位置:不在 default profile,在
profiles/win10-u533b-u751f/.env:526。 - desktop 不参与 Nix 构建:它是 git 安装目录下的预编译产物,所以「补编译链、重跑 npm ci」对它无效;真正的作用面只有 nix-ld 库集与进程启动环境变量。
- 另一处未清失败单元:
app-trilium-notes@796a2c2a…service 仍 failed。
已验证有效的修复(按判据计)
| 动作 | 生效判据(实测) |
|---|
| nix-ld 补 mesa / libGL / libGLU / fontconfig / freetype / gdk-pixbuf / libuuid / libpulseaudio / openssl | 库数 437 → 525;四个关键库自 gen47 起存在 |
| 重启系统 | desktop 进程环境实测 NIX_LD_LIBRARY_PATH=/run/current-system/sw/share/nix-ld/lib;14:32:32 启动后稳定运行、0 崩溃 |
| gateway 侧处理 | 本次开机 already owns this host = 0、Scheduled restart = 0 |
| sandbox fallback 重置 | 文件值为 {"state":"ok"} |
下次同类故障的判据顺序
coredumpctl list | grep -i Hermes —— 先拿信号与二进制路径。- 信号是 SIGILL ⇒ 直接判为 Chromium
IMMEDIATE_CRASH(主动自杀),别去找「非法指令」。 ls $(readlink /nix/var/nix/profiles/system-N-link)/sw/share/nix-ld/lib | wc -l —— 逐世代比库数,最快最硬(本例 437 vs 525 一眼定案)。tr '\0' '\n' < /proc/<desktop 主进程>/environ | grep NIX_LD —— 看运行进程实际拿到什么,不看配置「应该」给什么。- drkonqi 自身的 SIGABRT 全是噪音,忽略。
遗留待办
- 把盘1 追平:同步
/etc/nixos + /nix,重建盘1 的 system 与引导条目 —— 否则盘1 首启会原样复发。 - 清
profiles/win10-u533b-u751f/.env:526 的 Windows TMPDIR(属另一个 profile,需你点头)。 - 时钟 8 小时偏差:查是否 RTC 被 Windows 写成本地时间导致启动瞬间读错。