03 · 安装、引导与首登¶
Quattro 不把安装写成一个“万能 root 脚本”。它把必须 root 的系统副作用、必须知道 owner 的 home 操作,以及必须进入图形会话的动作分成三个关卡。
为什么不能一次做完¶
安装时可用的上下文逐步增加:
| 阶段 | 已知/可用 | 尚不可依赖 |
|---|---|---|
| system apply | root、目标磁盘、pacman、systemd system | 用户 D-Bus、DConf、通知、音频 session |
| user finalize | owner、HOME、用户文件权限 | 已运行的 Shell、稳定的图形服务 |
| first run | graphical session、user systemd、D-Bus | 无需再假装是安装环境 |
把动作放错阶段会产生经典问题:root 拥有用户文件、systemctl --user 连接不到 bus、音频调优找不到 sink、欢迎通知无处显示。
入口一:omarchy-apply-system¶
该入口要求 root,接收安装用户与 deferred 模式等参数,建立统一日志和环境,然后按顺序执行三组脚本:
flowchart TD
Apply[omarchy-apply-system] --> Guard{EUID == 0?}
Guard -->|否| Stop[拒绝]
Guard -->|是| Env[参数/环境/日志]
Env --> Hardware[omarchy-apply-hardware]
Hardware --> Login[install/login/all.sh]
Login --> Post[install/post-install/all.sh]
Env --> Config[install/config/all.sh]
系统配置集合涵盖主题系统准备、登录锁定、PAM、SSH、Docker、Snapper、locate、systemd 服务和防火墙等。硬件集合单独编排,是因为每一项都需要先探测再幂等应用。
编排脚本为何多用 source¶
顶层安装器把阶段脚本 source 到同一个受控 shell 中,因此它们共享安装上下文、错误策略和 helper。好处是日志与失败传播统一;代价是变量命名需要克制,脚本不能假设独立进程隔离。
入口二:用户 finalizer¶
omarchy-provision-user 的首要防线是拒绝 root。随后它检查 finalization marker,避免重复完成一次性动作。
核心工作包括:
- 建立 AI agent skills 的用户链接;
- 修正 XDG user dirs 和 GTK bookmarks;
- 执行
install/user/all.sh中的 Git、mise、主题、XCompose 等动作; - 刷新 desktop 应用库、默认浏览器与
mailto; - 对全新安装,把已有迁移标记为已应用。
最后一项很关键:全新安装得到的包内容已经是当前状态,再执行“从历史版本迁到当前”的脚本既浪费又可能破坏状态。因此 fresh install 创建 migration markers,升级机器则由 migrator 真正运行脚本。
入口三:first-run¶
first-run marker 与 finalization marker 分开:
first-run 会先确保 finalizer 已完成,然后:
- 安装或刷新 post-update hooks;
- 启用用户级 systemd units;
- 应用 GNOME/GTK 相关设置;
- 配置初始音频调优;
- 等待通知服务可用;
- 展示欢迎信息与 Wi-Fi 提示。
sequenceDiagram
participant G as 图形登录
participant F as omarchy-first-run
participant P as provision-user
participant US as user systemd/D-Bus
participant Q as Quickshell 通知
G->>F: 启动 first-run
F->>P: 确保 finalization
P-->>F: done
F->>US: enable units / apply settings
F->>Q: 等待服务并发送欢迎
alt 全部成功
F->>F: 写 first-run marker
else 任一步失败
F->>F: 记录错误,不写 marker
end
marker 是提交记录,不是开始记录¶
只有所有必需动作成功后才写 marker。若中间失败,下次登录会重试。这里可把 marker 看成一个极简事务提交:它不回滚已成功的幂等动作,但阻止“半完成”被误认为完成。
deferred 模式怎样跨 reboot¶
当安装过程暂时没有 owner,会留下 pending 状态。首启的 provisioning service 完成 owner 创建和 finalization。与其把未知用户名硬编码进系统镜像,这种方式把决定延迟到拥有足够信息的时刻。
stateDiagram-v2
[*] --> Deferred: apply-system --deferred
Deferred --> Pending: 写系统状态
Pending --> OwnerKnown: 首启 setup/provision
OwnerKnown --> UserFinalized
UserFinalized --> GraphicalFirstRun
GraphicalFirstRun --> Ready
幂等的真实含义¶
这里的幂等不是“脚本可以无限重复且绝无副作用”,而是三种策略的组合:
- 状态探测:服务、包、文件是否已经满足目标;
- marker 跳过:一次性生命周期动作成功后不再进入;
- 可安全重放:失败前已完成的小步骤再次执行不会造成冲突。
所以排障时不要第一反应删除所有 marker。先看 marker 对应的承诺是否真的成立;migration marker、first-run marker 与普通生成状态有完全不同的语义。
失败观察点¶
| 症状 | 先检查 | 解释 |
|---|---|---|
| 系统包在但用户配置缺 | provisioning pending / finalize marker | 可能只完成 root 阶段 |
| 用户 unit 没启用 | first-run marker 与图形会话日志 | 不能只看 finalizer |
| 新机运行历史迁移出错 | migration markers 是否在 fresh install 创建 | 新安装应直接视为 current |
| home 文件归 root | 是否绕过 omarchy-provision-user 的用户边界 |
用户阶段不应 root 执行 |
| 欢迎通知不出现 | Shell 通知服务是否已就绪 | first-run 明确等待图形服务 |
关键源码索引¶
bin/omarchy-apply-system— root 系统应用入口install/config/all.sh— 系统配置编排install/hardware/all.sh— 硬件动作顺序bin/omarchy-provision-user— 用户 finalization 与迁移初始化bin/omarchy-first-run— 图形会话首登动作install/user/first-run/enable-user-units.sh— 用户服务启用
机器准备好以后,下一条链从 display manager 进入会话:04 · 会话启动与 Hyprland。