diff --git a/chv-guest/build.sh b/chv-guest/build.sh index 143523e..d256ef5 100755 --- a/chv-guest/build.sh +++ b/chv-guest/build.sh @@ -323,7 +323,14 @@ VC_ARGS=(-a "$OUT/disk.raw" --run-command 'dpkg-query -W -f "\${Package} \${Version}\n" > /app/guest-versions-dpkg.txt; pip3 freeze > /app/guest-versions-pip.txt || true' --run-command 'useradd --system --home-dir /var/lib/chv-browser --shell /usr/sbin/nologin chv-browser && mkdir -p /var/lib/chv-browser /run/chv/shots && chown chv-browser:chv-browser /var/lib/chv-browser /run/chv/shots && chmod 0755 /run/chv /run/chv/shots' --run-command 'printf "[Unit]\nDescription=CHV cell broker (Muse P2)\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=/usr/bin/python3 /usr/local/bin/chv-broker\nRestart=on-failure\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-broker.service' - --run-command 'printf "[Unit]\nDescription=CHV browser sub-agent (Muse P2)\nAfter=network.target cloud-final.service\n\n[Service]\nType=simple\nUser=chv-browser\nGroup=chv-browser\nExecStart=/usr/bin/python3 /usr/local/bin/chv-browser\nRestart=always\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-browser.service' + # 浏览器单元排在数据盘挂载之后(home-chv-workspace.mount 是 + # cloud-init 生成的挂载单元)。绝不能 After=cloud-final.service: + # cloud-final 自己 After=multi-user.target,与浏览器的 + # Before=multi-user.target(WantedBy 隐含)成环,systemd 启动时 + # 直接删掉浏览器任务(2026-11-08 构建 #9 驱动实证:服务从未启动、 + # NRestarts=0、无日志,journal 明言 Job deleted to break cycle; + # 构建 #8 同款问题一直被手动 restart 掩盖)。 + --run-command 'printf "[Unit]\nDescription=CHV browser sub-agent (Muse P2)\nAfter=network.target home-chv-workspace.mount\n\n[Service]\nType=simple\nUser=chv-browser\nGroup=chv-browser\nExecStart=/usr/bin/python3 /usr/local/bin/chv-browser\nRestart=always\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-browser.service' --run-command 'printf "[Unit]\nDescription=CHV guest runtime daemon (stage 2: heartbeat/resources/snapshot)\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=/usr/bin/python3 /usr/local/bin/chv-daemon\nRestart=always\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-daemon.service' # 构建 #6 驱动实证(2026-11-08):execd 单元缺 KillMode 时默认 # control-group,kill -9 主进程后 systemd 重启会 SIGTERM 整个 diff --git a/cloud/tests/test_chv_opt_stage3.py b/cloud/tests/test_chv_opt_stage3.py index 69b8405..006b1a0 100644 --- a/cloud/tests/test_chv_opt_stage3.py +++ b/cloud/tests/test_chv_opt_stage3.py @@ -547,14 +547,19 @@ class BuildWiringTest(unittest.TestCase): self.assertIn(".chv-browser-profile", text) self.assertIn("chown chv-browser:chv-browser", text) - def test_build_sh_browser_unit_always_restarts_after_cloud_final(self): + def test_build_sh_browser_unit_orders_after_data_disk_mount(self): + # 绝不能 After=cloud-final.service:cloud-final 自己 + # After=multi-user.target,与浏览器的 Before=multi-user.target + # 成环,systemd 启动时直接删掉浏览器任务(2026-11-08 构建 #9 + # 驱动实证)。排在数据盘挂载单元之后才是真依赖。 text = (ROOT / "chv-guest" / "build.sh").read_text() idx = text.find("Description=CHV browser sub-agent") self.assertGreater(idx, 0) - block = text[idx:idx + 800] + block = text[idx:idx + 1200] self.assertIn("Restart=always", block) - self.assertIn("After=network.target cloud-final.service", + self.assertIn("After=network.target home-chv-workspace.mount", block) + self.assertNotIn("cloud-final.service", block) def test_tmpfiles_lets_browser_bind_its_socket(self): # 阶段 3 live 根因:/run/chv 0755 root:root 时 chv-browser @@ -617,7 +622,7 @@ class BuildWiringTest(unittest.TestCase): self.assertEqual(proc.returncode, 0, proc.stderr) out = proc.stdout + proc.stderr self.assertIn("Restart=always", out) - self.assertIn("cloud-final.service", out) + self.assertIn("home-chv-workspace.mount", out) if __name__ == "__main__":