将系统级 systemd Target 桥接到用户实例

发布: (2026年1月19日 GMT+8 22:49)
5 min read
原文: Dev.to

Source: Dev.to

概述

当使用 systemd 时,许多服务依赖 network-online.target 来确保网络在它们启动之前已完全就绪。
network-online.target 存在于系统层级,但现代工作流常常在 用户 systemd 实例中运行长期服务(例如,用户管理的守护进程、开发工具、每用户代理)。

此处描述的桥接会在系统达到“网络在线”状态时,立即在特定用户的 systemd 实例内部触发一个标记目标,从而使用户服务在启动时能够可靠地依赖 network-online.target

组件

  1. 安装脚本 (install.sh) – 设置所需的系统和用户单元。
  2. 用户级标记单元 (network-online.target) – 在用户实例中表示“网络已上线”。
  3. 系统级模板服务 (user‑network‑online@.service) – 等待系统网络上线后,为给定的 UID 启动用户级目标。

这些一起确保用户服务可以声明对 network-online.target 的依赖,即使实际的网络就绪信号来源于系统层面。

处理用户 Systemd 生命周期

默认情况下,用户的 systemd 实例与交互式登录绑定;如果用户未登录,该实例可能不存在,从而阻止用户服务在启动时启动。

安装脚本启用 linger

loginctl enable-linger $USER

启用 linger 后,即使没有活动会话,用户的 systemd 实例也可以运行,这是一项在启动过程中启动用户服务的前提条件。

用户级标记单元

将以下文件放置在 ~/.config/systemd/user/network-online.target

[Unit]
Description=User-level Network is Online (marker only)
Documentation=man:systemd.special(7)

该单元故意保持简洁——它 执行任何网络检查。它唯一的目的在于提供一个同步点,以便用户服务可以声明:

After=network-online.target
Wants=network-online.target

System‑Level Service Template

Create /etc/systemd/system/user-network-online@.service with the following content:

[Unit]
Description=Trigger user-level network-online.target for %i
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
User=%i
Environment=XDG_RUNTIME_DIR=/run/user/%i
ExecStart=/usr/bin/systemctl --user start network-online.target

[Install]
WantedBy=multi-user.target
  • 该服务在系统的 network-online.target 之后 运行,确保仅在系统认为网络已就绪时才触发。
  • 它执行一次性命令以启动用户级的 network-online.target
  • 设置 XDG_RUNTIME_DIR 可将 systemctl --user 指向目标用户实例的正确运行时目录。

安装脚本

#!/bin/sh

# Enable linger for the current user
loginctl enable-linger $USER

# Install the system unit
sudo cp -t /etc/systemd/system/ user-network-online@.service
sudo systemctl daemon-reload

# Install the user target
USER_SYSTEMD_PATH="$HOME/.config/systemd/user"
mkdir -p "$USER_SYSTEMD_PATH"
cp -t "$USER_SYSTEMD_PATH" network-online.target
systemctl --user daemon-reload

# Enable and start the templated service for the current UID
sudo systemctl enable --now user-network-online@$(id -u).service

脚本执行以下操作:

  1. 为当前用户启用 linger。
  2. 将系统单元复制到 /etc/systemd/system/ 并重新加载系统守护进程。
  3. 将用户目标安装到 ~/.config/systemd/user/ 并重新加载用户守护进程。
  4. 为当前 UID 启用并启动 user-network-online@.service。由于该单元的 WantedBy=multi-user.target,它会在正常的启动序列中自动运行。系统一旦达到 network-online.target,就会触发用户的 network-online.target,从而以有序、基于依赖的方式启动依赖的用户服务。

结果工作流

  1. System 决定网络何时为“在线”。
  2. system‑level service (user-network-online@.service) 启动 user‑level marker (network-online.target)。
  3. User services 声明 After=network-online.target(或 Wants=network-online.target)时,可安全启动,因为已知网络已就绪。
  4. 即使用户未登录,得益于 linger,所有内容也会在启动时自动运行。

这种轻量级模式符合 systemd 的依赖模型,并为必须等待可靠网络可用性的用户管理后台服务提供了坚实的基础。

Back to Blog

相关文章

阅读更多 »