# 路线 A 落地记录：Netdata 大屏（核显 kiosk）

- **日期**：2026-09-27
- **机器**：GPU 机 zywpc（192.168.31.31），**2560×1440** 屏，显示器已从 RTX 5060 Ti 移到**主板口（Intel 核显）**
- **目标**：不再手搓 tmux 布局，改用社区成熟方案——**Netdata 采集 + 浏览器 kiosk 全屏**
- **当前状态**：✅ 已跑起来（`cage` + `qutebrowser` + Netdata v2.11.1 全屏），⚠️ 落地页深链待定（见第六节）

---

## 一、显示拓扑（改造后）

```
card1 = NVIDIA（四口全 disconnected，纯计算卡）
card2 = Intel 核显（HDMI-A-2 connected → 就是那块 2K 屏）
fb0   = i915drmfb          ← 控制台/图形全走核显，独显 16GB 不再被显示栈占用
```

## 二、Netdata（采集与网页）

- 版本 **v2.11.1**（官方 kickstart 安装），监听 `0.0.0.0:19999` → 局域网直达
- **局域网入口：http://192.168.31.31:19999**
- 采集器（`/etc/netdata/go.d/`）：
  - `nvidia_smi.conf` → **GPU 13 张图**：利用率 / 显存占用 / 温度 / 功耗 / 风扇 / 时钟 / 编解码器 / PCIe / BAR1 / MIG
  - `portcheck.conf` → **端口存活 18 张图**：8189(ComfyUI)、8080(LLM)、1234(LM Studio)、3013/6020(H3 Studio)、22(SSH)，每口有 status / 连接延迟 / 状态持续时长
- ⚠️ **踩坑**：用 `printf 密码 | sudo -S` 这种封装**不能再接 heredoc 写文件**——stdin 被密码管道吃掉，写进去的是密码本身（本次第一版配置就是 11 字节的密码）。正确做法：本地写文件 → scp → `install -o netdata -g netdata`。

## 三、Kiosk 图形栈（Wayland）

| 组件 | 作用 | 说明 |
|---|---|---|
| **cage 0.1.5** | Wayland kiosk 合成器 | `cage -s -d -- <app>`；`-s` 允许切 VT，`-d` 不画客户端装饰 |
| **qutebrowser 2.5.4** | 浏览器（QtWebEngine = Chromium 内核） | 用专用 `--basedir` 配置目录，`tabs.show/statusbar.show = never` → **纯页面全屏** |
| **grim 1.4.0** | kiosk 内截图 | 验证渲染用（`--shot` 模式） |
| **Netdata 落地页** | 显示内容 | 见第六节 |

关键脚本：`/usr/local/bin/netdata-kiosk.sh`、`/usr/local/bin/display-mode`、`~/.config/qutebrowser-kiosk/{config/config.py,kiosk.css}`

## 四、模式切换（一行命令）

```bash
display-mode kiosk qutebrowser   # 图形大屏（cage + 浏览器 + Netdata）
display-mode console             # 回文本控制台面板（btop + 状态栏）
display-mode status              # 看当前模式与运行状态
```

原理：`~/.display-mode` 里写 `kiosk [浏览器]`；tty1 登录时 `~/.bash_profile` → `sysmon.sh` 读它 → `exec netdata-kiosk.sh`；否则走原控制台面板。

## 五、这一路线踩过的 8 个坑（都实测过）

1. **从 SSH 起 Wayland 合成器必失败**：`libseat: Could not open target tty: Permission denied` → cage 必须在 **tty1 的登录会话**里启动（`display-mode` 正是这么做的）。
2. **`epiphany -a/--application-mode` 不吃 URL**：它要的是 `.desktop` 文件（报 `Invalid desktop file passed to --application-mode`）→ 弃用 epiphany 的 app 模式。
3. **qutebrowser 缺 Qt Wayland 插件**会回退 X11 → 在 cage 下**把合成器一起拖死**（`Wayland events: Connection reset by peer`）→ 装 `qtwayland5` 并 `QT_QPA_PLATFORM=wayland`。
4. **qutebrowser 配置里写错一个不存在的设置项会直接崩**（我们写 `c.messages.mouse` → `KeyError: 'command-history'`）。只写确定存在的项。
5. **Netdata v2 的登录浮层**：社区答案是 URL 加 `/v3`，但 **v2.11 上 `/v3` 会 ChunkLoadError**（chunk 路径不匹配）；`/old/` 经典仪表盘也因 base-path 全部报 `Unexpected token < in JSON`。**最终解法：仍用根路径，用 qutebrowser 用户样式表把浮层容器 `#splashMessageContainer.splash-message` 永久隐藏**（仪表盘就在它后面，已渲染）。
6. **`pkill -f <模式串>` 会自杀**：命令串里含 `cage -s` 时，`pkill -9 -f "cage -s"` 把执行命令的 SSH shell 一起杀了（整条命令静默不执行）→ 一律用 `pkill -x <进程名>`。
7. **Wayland 下 `dd if=/dev/fb0` 抓不到内容**（KMS 客户端接管后 fbdev 被 detach）→ kiosk 内截图必须用 `grim`（本脚本的 `--shot` 模式）。
8. **`~/.display-mode` 分支没装上时** tty1 仍会起老面板——排查时先用 `grep -n display-mode /usr/local/bin/sysmon.sh` 确认脚本真的更新了。

## 六、当前未完成的部分

Kiosk 现在显示的是 **Netdata 的欢迎/统计落地页**（指标总数 5,132、分层存储表、底部 Database/System/Modules/Directories 标签），**图表在底部标签里**。可选下一步：

- **A（最省事）**：在屏幕上点一次底部 `System` 标签即可看图表；若要每次开机直达，需要定出该标签的深链参数（落地页用 `data-tab="1..4"` + `location.hash` 解析，键名未公开）。
- **B（最稳）**：改用 **Grafana + grafana-kiosk**——Grafana 有官方 kiosk 工具、Playlist 轮播、社区看板（1860/12239），是"生产级大屏"的标准做法，代价是组件更多。
- **C（自定义）**：在 Netdata UI 里拖一个 **Custom Dashboard**（只放 GPU+端口+CPU/内存），再把 kiosk 指向它的 URL——最贴近"开机即固定大屏"的需求。

## 七、资源占用与安全

- 显示栈全部跑在**核显**上：**独显显存 0 占用**（`nvidia-smi` 里现在只有 ComfyUI 的 CUDA 上下文，约 316 MiB）
- kiosk 栈占的是**系统内存**（Chromium 渲染 + 合成器，约数百 MB；机器 30 GB 内存，余量充足）
- Netdata 自身约 100–200 MB 内存、默认保留 1 GB/层的本地库（`/var/cache/netdata`）
- 新增监听：`19999`（Netdata）。**如需限制只本机可见**，可在 `netdata.conf` 里把 `bind to` 改成 `127.0.0.1`。

## 八、复现清单（本目录 `scripts/`）

| 脚本 | 作用 |
|---|---|
| `install-netdata.sh` | 官方 kickstart 安装 Netdata |
| `netdata-nvidia_smi.conf` / `netdata-portcheck.conf` | 两个采集器配置 |
| `netdata-collectors.sh` | 安装采集器配置并自检（**注意其中的写法已修正 stdin 坑**） |
| `install-kiosk.sh` | 装 cage / epiphany / grim |
| `netdata-kiosk.sh` | kiosk 启动器（含 `--shot` 截图验证模式） |
| `qutebrowser-kiosk-config.py` + `kiosk.css` | 浏览器 kiosk 配置与浮层隐藏样式 |
| `display-mode.sh` | 一键切换 kiosk / console |
| `igpu-check.sh` | 核显启用状态检测 |

## 九、截图

- `screenshots/kiosk-final.png` —— 浮层已隐藏后的 kiosk 实际画面（2K 全屏）
- `screenshots/kiosk-netdata2.png` —— 隐藏前的样子（可见"Welcome to Netdata"浮层与背后的仪表盘）
