200字
Linux Services
2026-02-20
2026-02-20

1. 什么是 Service / Daemon

在 Linux 里,Daemon(守护进程)是在后台持续运行、不与终端直接交互的进程。

  • Daemon 这个词源自希腊神话中介于神与人之间的精灵,寓意"在背后默默守护"。Unix 沿用了该命名,进程名通常以字母 d 结尾,如负责 SSH 连接的 sshd、负责 Web 服务的 httpd、以及 Linux 现代 init 系统本身的 systemd
  • 一个典型 daemon 的生命周期是:系统启动时由 init 系统拉起,父进程为 PID 1,与任何控制终端完全脱离,然后在后台长期运行,直到被显式停止或系统关机。也有部分 daemon 采用"按需激活"的方式,平时不占资源,有请求时才被唤醒(如 socket activation)。

Service 则是对Daemon的抽象封装。在现代 Linux 中,service 指由 init 系统(即 systemd)统一管理的、具有完整生命周期控制的程序单元——启动、停止、重启、开机自启、依赖排序,都由 systemd 负责。

  • 可以这样理解:daemon 是进程层面的概念,service 是管理层面的概念,两者通常指向同一个东西,但角度不同。

2. systemd 架构简述

systemd 是目前几乎所有主流 Linux 发行版的默认 init 系统,以 PID 1 的身份运行,是系统中第一个启动、最后一个退出的进程,负责统筹整个用户空间的初始化。

systemd 的职责不止"启动服务",还是一套完整的系统管理框架:

PID 1: systemd
├── unit 文件解析 & 依赖图构建    # 读取 .service/.target 等配置,构建启动顺序
├── 并行启动                      # 依赖满足即立即启动,不串行等待
├── cgroup 隔离                   # 每个服务独立 cgroup,精准追踪子进程、限制资源
├── journal 日志收集              # 统一收集所有服务的 stdout/stderr,替代分散的日志文件
└── socket/dbus/timer activation  # 按需激活:有连接才启动服务,有时间才触发任务

管理的基本单元叫做 Unit,不同类型的 unit 对应不同的系统资源,常用的有:

类型 后缀 用途
Service .service 管理一个进程/守护进程的完整生命周期
Target .target 同步点,如 multi-user.target
Timer .timer 定时触发,是 cron 的现代替代
Socket .socket socket 激活,有连接时才拉起对应 service
Mount .mount 管理文件系统挂载点

日常打交道最多的是 .service,Alist、Clash 等软件的配置文件都属于 Service


3. Service Unit 文件结构

[Unit]
Description=服务描述
Documentation=https://...        # 可选文档链接
Wants=network-online.target      # 弱依赖:目标最好存在,失败不阻止本服务
Requires=xxx.service             # 强依赖:目标失败则本服务也失败
After=network-online.target      # 顺序:在目标之后启动(不隐含依赖)
Before=xxx.service               # 顺序:在目标之前启动

[Service]
Type=simple          # 见下方 Type 说明
ExecStart=/usr/bin/xxx --args
ExecStop=/usr/bin/xxx stop       # 可选,默认 SIGTERM
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/path/to/dir
User=nobody
Group=nobody
Environment=VAR=value
EnvironmentFile=/etc/xxx.env
Restart=on-failure   # 见下方 Restart 说明
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target       # 系统服务挂载点
# WantedBy=default.target        # 用户服务挂载点

Type 详解

Type 行为 适用场景
simple ExecStart 进程即主进程,启动即视为就绪 大多数服务
exec 等待 exec() 成功后才视为就绪(比 simple 更严格) 需要确认执行的场景
forking 父进程 fork 后退出,子进程成为 daemon 传统 SysV daemon
oneshot 进程退出后视为完成,适合脚本 初始化脚本
notify 进程主动通过 sd_notify() 通知就绪 支持 systemd 协议的服务
dbus 通过 D-Bus 名称确认就绪 D-Bus 服务

Restart 策略

触发重启的条件
no 从不(默认)
always 任何退出(含正常退出)
on-failure 非零退出码、信号异常终止
on-abnormal 信号/超时,不含正常退出
on-success 仅正常退出(exit 0)

4. 系统服务 vs 用户服务

系统服务 用户服务
Unit 路径 /etc/systemd/system/(管理员) /usr/lib/systemd/system/(软件包) ~/.config/systemd/user/
运行身份 root 或指定 User 当前登录用户
启动时机 系统引导时 用户登录后
管理命令 systemctl <cmd> systemctl --user <cmd>
WantedBy multi-user.target default.target
日志查看 journalctl -u xxx journalctl --user -u xxx
lingering 启用后可在无用户登录时运行

启用 lingering(用户服务开机自启,无需登录):

loginctl enable-linger $USER

5. systemctl 常用命令速查

服务管理

# 启动 / 停止 / 重启 / 重载配置
systemctl start   <unit>
systemctl stop    <unit>
systemctl restart <unit>
systemctl reload  <unit>      # 重载服务自身配置(不重启进程)

# 开机自启
systemctl enable  <unit>      # 创建 symlink
systemctl disable <unit>      # 删除 symlink
systemctl enable --now <unit> # enable + 立即启动

# 状态查看
systemctl status  <unit>      # 详情 + 近期日志
systemctl is-active  <unit>   # active / inactive
systemctl is-enabled <unit>   # enabled / disabled

# 重载 unit 文件(修改后必须执行)
systemctl daemon-reload

系统级操作

以下命令可加 --user 来查看用户服务

systemctl list-units --type=service          # 列出所有 service
systemctl list-units --type=service --failed # 列出失败的
systemctl list-unit-files                    # 列出所有 unit 文件及启用状态
systemctl cat <unit>                         # 查看 unit 文件内容
systemctl edit <unit>                        # 创建 drop-in 覆盖文件
systemctl show <unit>                        # 显示所有属性(机器可读)

用户服务(加 --user

systemctl --user start   alist.service
systemctl --user enable  alist.service
systemctl --user status  alist.service
systemctl --user daemon-reload
journalctl --user -u alist.service -f

6. 日志:journalctl

journalctl -u <unit>             # 查看某服务全部日志
journalctl -u <unit> -f          # 实时跟踪(tail -f 效果)
journalctl -u <unit> -n 50       # 最近 50 行
journalctl -u <unit> --since "1 hour ago"
journalctl -u <unit> -p err      # 仅 error 级别以上
journalctl --user -u <unit>      # 用户服务日志
journalctl -b                    # 本次启动日志
journalctl -b -1                 # 上次启动日志

7. 实例分析

实例 1:Alist 用户服务

# ~/.config/systemd/user/alist.service
[Unit]
Description=Alist User Service
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
WorkingDirectory=%h/.config/alist          # %h = $HOME
ExecStart=/usr/bin/alist server --data %h/.config/alist/data
Restart=on-failure

[Install]
WantedBy=default.target

要点解读:

  • 用户服务:放在 ~/.config/systemd/user/WantedBy=default.target
  • %h 是 systemd specifier,展开为用户家目录(等价于 $HOME
  • Wants= + After= 组合:等待网络就绪,但网络失败不阻止启动
  • Restart=on-failure:崩溃自动重启,正常退出不重启

部署流程:

systemctl --user daemon-reload
systemctl --user enable --now alist.service
systemctl --user status alist.service

实例 2:Clash Verge 系统服务

# /etc/systemd/system/clash-verge-service.service
[Unit]
Description=Clash Verge Service helps to launch Clash Core.
After=network-online.target nftables.service iptables.service

[Service]
Type=simple
ExecStart=/usr/bin/clash-verge-service
Group=wenmou            # 以指定用户组运行(特权操作需要)
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

要点解读:

  • 系统服务:放在 /etc/systemd/system/WantedBy=multi-user.target
  • After= 列出多个依赖:等防火墙规则(nftables/iptables)加载后再启动,避免代理规则冲突
  • Group=wenmou:不以 root 运行,但保留组权限(用于 tun 设备、网络配置等)
  • Restart=always:无论何种原因退出都重启,配合 RestartSec=5 防止重启风暴
  • 注意:未设置 User=,意味着以 root 用户 + wenmou 组运行

部署流程:

sudo systemctl daemon-reload
sudo systemctl enable --now clash-verge-service.service
sudo systemctl status clash-verge-service.service

8. 常用 Specifiers(Unit 文件变量)

Specifier 含义
%h 用户家目录($HOME
%u 用户名
%U 用户 UID
%n unit 完整名称
%i 实例名(模板 unit @ 后的部分)
%t Runtime 目录(/run$XDG_RUNTIME_DIR

9. 常见问题排查

# 忘记服务名
systemctl list-units --type=service  
systemctl --user list-units --type=service

# 服务启动失败,查详情
systemctl status <unit>
journalctl -u <unit> -n 100 --no-pager

# 修改 unit 文件后忘记 daemon-reload
systemctl daemon-reload

# 查看服务实际执行的完整命令(specifier 展开后)
systemctl show <unit> -p ExecStart

# 用户服务无法开机自启(未登录时不运行)
loginctl enable-linger $USER

# 检查 unit 文件语法
systemd-analyze verify ~/.config/systemd/user/alist.service

10. 最佳实践

  1. 修改 unit 文件后必须 daemon-reload,否则 systemd 仍使用旧配置
  2. 优先用用户服务运行个人软件(Alist 等),避免不必要的 root 权限
  3. enable --now 一步完成开机自启 + 立即启动
  4. 不要直接编辑 /usr/lib/systemd/system/ 下的文件,应在 /etc/systemd/system/ 创建同名文件覆盖
  5. Restart=on-failure + RestartSec=5 是生产环境的常见组合,避免崩溃循环
  6. 日志优先用 journalctl -u <unit> -f 实时观察启动过程

评论