niri 的 systemd 会话集成:用 systemd 用户服务管理 mako、waybar、swaybg 与 swayidle
【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri
本篇技术指南介绍 niri(一个可滚动平铺的 Wayland 合成器)作为 systemd 会话运行时的完整集成方案:如何将mako、waybar、swaybg、swayidle等图形会话组件注册为 systemd 用户服务,使其随 niri 会话自动启动、停止,并支持独立的状态查看、日志追踪与按需重启。读者将掌握systemctl --user服务编排、自定义 unit 编写、跨注销驻留程序等实战技能,并理解 niri 会话与graphical-session.target的底层绑定关系。
背景:niri 会话与 systemd 的集成原理
从显示管理器(如 GDM、SDDM)启动 niri,或在 TTY 上运行niri-session时,niri 并非作为普通前台进程裸跑,而是以systemd 用户服务的形式纳入会话管理。这一点在 Getting-Started.md 中明确说明:niri-session脚本会额外将 niri 作为 systemd/dinit 服务启动,并拉起图形会话所需的graphical-session.target——门户服务(portal)等依赖此 target 才能绑定到图形会话。
这一机制的核心证据在仓库资源文件中:
- resources/niri.service:
BindsTo=graphical-session.target、Before=graphical-session.target,并以Type=notify运行niri --session;同时Wants=xdg-desktop-autostart.target,这也是下文将提到的 XDG 自启动开箱即用的根源; - resources/niri-session:脚本先执行
systemctl --user import-environment导入登录环境,再以systemctl --user --wait start niri.service启动会话,退出时通过systemctl --user start --job-mode=replace-irreversibly niri-shutdown.target强制停止graphical-session.target; - resources/niri-shutdown.target:
Conflicts=graphical-session.target graphical-session-pre.target,专门负责在登出时关停整个图形会话。
正是因为有这套完整的graphical-session.target生命周期,运行在会话内的程序(mako通知守护进程、xdg-desktop-portal等)才能获得正确的会话环境与生命周期管理。
为什么要用 systemd 服务,而不是 spawn-at-startup
niri 的配置文件本身提供了 spawn-at-startup 指令,可在启动时直接拉进程:
spawn-at-startup "waybar" spawn-at-startup "alacritty"但这种方式启动的进程脱离 systemd 管理。而本指南展示的 systemd 方案带来的直接收益是:可以方便地监控这些程序的状态与输出,并在编辑配置后单独重启或重载它们,例如修改 waybar 配置后执行systemctl --user restart waybar.service,而无需重启整个会话。
另外值得补充的是,niri 作为 systemd 会话运行时开箱即用地支持 xdg-desktop-autostart(得益于 resources/niri.service 中的Wants=xdg-desktop-autostart.target):在 GNOME 中配置过自启动的应用,在 niri 中也会"直接生效",无需任何手动spawn-at-startup配置。两种方式可按场景互补使用。
实战:将四个常用组件接入 niri 会话
以下完整演练对应 Example-systemd-Setup.md 的全部步骤,涉及四个典型场景:自带 unit 的服务、自带 unit 的栏、需要自定义 unit 的背景程序、需要自定义 unit 的锁屏/电源管理程序。
第一步:安装软件
在 Fedora 系发行版上:
sudo dnf install mako waybar swaybg swayidle其他发行版请使用对应的包管理器安装同名软件包。
第二步:mako 与 waybar——直接复用自带的 systemd unit
mako(Wayland 通知守护进程)和waybar(Wayland 状态栏)在打包时已随附 systemd 用户 unit,无需手写。只需将它们挂到 niri 会话上:
systemctl --user add-wants niri.service mako.service systemctl --user add-wants niri.service waybar.serviceadd-wants的实质是在~/.config/systemd/user/niri.service.wants/目录下创建符号链接——这是 systemd 专门用于表达"随某服务一起启动"的目录。这样 niri 会话启动时,systemd 会自动拉起这两个服务;会话结束(graphical-session.target停止)时,BindsTo关系会连带将它们停止。
之后编辑 waybar 配置时,可单独重启:
systemctl --user restart waybar.service第三步:swaybg——编写自定义 unit 传递命令行参数
swaybg不提供 systemd unit,因为背景图片必须作为命令行参数传入,无法在 unit 内预先固化。因此需要自定义~/.config/systemd/user/swaybg.service:
[Unit] PartOf=graphical-session.target After=graphical-session.target Requisite=graphical-session.target [Service] ExecStart=/usr/bin/swaybg -m fill -i "%h/Pictures/LakeSide.png" Restart=on-failure关键点说明:
PartOf=graphical-session.target:声明本服务属于图形会话,会话停止时本服务随之停止;After=graphical-session.target与Requisite=graphical-session.target:确保仅在图形会话已启动后才运行,若 target 未激活则不启动(Requisite比After更强,会话未就绪时直接放弃启动);%h由 systemd 展开为你的家目录路径;请将-i后的图片路径替换为你自己的壁纸;Restart=on-failure:进程非正常退出时自动重启,提升壁纸守护的健壮性。
编辑完 unit 文件后,必须重载 systemd 才能识别改动:
systemctl --user daemon-reload然后挂到 niri 会话:
systemctl --user add-wants niri.service swaybg.service第四步:swayidle——用自定义 unit 整合锁屏与显示器休眠
swayidle同样不自带 systemd unit,需要自定义~/.config/systemd/user/swayidle.service:
[Unit] PartOf=graphical-session.target After=graphical-session.target Requisite=graphical-session.target [Service] ExecStart=/usr/bin/swayidle -w timeout 601 'niri msg action power-off-monitors' timeout 600 'swaylock -f' before-sleep 'swaylock -f' Restart=on-failure这段配置实现的是经典的空闲电源管理链:空闲 600 秒(10 分钟)时锁屏(swaylock -f),再空闲 1 秒(累计 601 秒)后调用niri msg action power-off-monitors关闭显示器;系统进入休眠(before-sleep)前同样先锁屏。-w表示与 systemd 的 sleep 状态联动。
其中niri msg action power-off-monitors是 niri 内置的显示器休眠动作,与默认配置 resources/default-config.kdl 中的Mod+Shift+P { power-off-monitors; }键位绑定指向同一实现。关屏后,任何输入(移动鼠标或按键)即可唤醒。
随后照例执行:
systemctl --user daemon-reload systemctl --user add-wants niri.service swayidle.service效果验证与管理操作
完成以上步骤后,这三个工具会随 niri 会话一起启动、随会话退出而停止。日常管理命令包括:
# 查看服务状态与日志 systemctl --user status waybar.service journalctl --user -u waybar.service # 编辑配置后单独重启 systemctl --user restart waybar.service移除某个自启动服务:删除~/.config/systemd/user/niri.service.wants/中对应的符号链接,然后执行systemctl --user daemon-reload即可,无需改动其他配置。
进阶:跨注销运行常驻程序
在 niri 会话中"注销"(退出 niri)会终止所有在会话内启动的程序——这是图形会话的生命周期约束。但某些程序(如tmux、dtach或远程下载任务)希望跨注销继续存活。解决办法是用瞬态 systemd scope(transient scope)将其从会话的生命周期中剥离:
systemd-run --user --scope tmux new-sessionsystemd-run --user --scope会为程序创建一个独立的瞬态 scope 单元,使其不再受graphical-session.target停止的影响,从而在 niri 退出后依然驻留运行。这与niri-shutdown.target强制关停会话 target 的机制形成对照:scope 游离于会话 target 之外,因此得以幸存。
常见问题与补充说明
- 环境变量未生效:
niri-session脚本通过登录 shell 运行,并在启动前调用systemctl --user import-environment将WAYLAND_DISPLAY、DISPLAY、XDG_SESSION_TYPE、XDG_CURRENT_DESKTOP、NIRI_SOCKET等导入 systemd(见 resources/niri-session)。但这些变量不会传播到 systemd 全局环境,因此在 Configuration:-Miscellaneous.md 中特别提醒:通过 systemd 启动的应用(如桌面外壳的启动器)可能看不到这些变量。 - 非 systemd 环境:如果系统没有 systemd,
niri-session也支持 dinit(见 resources/niri-session 中的dinitctl分支);两者都没有时,请直接使用niri --session,但此时没有图形会话 target,依赖它的门户服务可能无法正常工作。 - 打包安装位置:若从源码自行打包,Packaging-niri.md 给出了资源文件的标准安装位置:
niri-session与niri.desktop分别安装到/usr/local/bin/与/usr/local/share/wayland-sessions/,niri.service与niri-shutdown.target(systemd 相关)安装到/etc/systemd/user/。
结语
把桌面组件接入 systemd 用户会话,是让 niri 桌面保持"可观测、可管理"的关键一步:mako、waybar直接挂载即用,swaybg、swayidle通过自定义 unit 融入会话生命周期,systemd-run --user --scope则为跨注销常驻程序提供了出口。这套模式同样适用于其他任何需要与 niri 会话同生共死的程序——只需遵循PartOf/After/Requisite三段式 unit 模板与add-wants挂载流程即可。
【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考