⏰ 第01章 · Systemd 基础
unit/target 概念
Systemd 基础¶
这一章先建立"服务是怎么被这台机器拉起来的"这个整体认知。你在这台 Ubuntu 24.04 服务器上敲 systemctl 时,背后有一套统一的进程管理框架在替你干活——它就是 systemd。学完这章,你会明白:一条 node server.js 为什么能被"开机自启、挂了自动拉起",又是被谁记录下来的。
从 SysV init 到 systemd¶
Linux 机器开机后,内核做完初始化,会启动第一个用户态进程,它的 PID 恒为 1,叫 init。所有其他进程——包括你的 shell、你的 node 服务——不是它的孩子,就是它的孩子的孩子。这个 PID 1 进程决定了一个系统的启动和管理方式。
传统方案叫 SysV init(RHEL 6、Debian 7 及更早),它的毛病是:
- 启动任务是串行的,一个起完才起下一个,开机慢;
- 用一堆
/etc/rc?.d/里的脚本管理,难读、难配、难并行; - 没有"服务崩溃自动重启"这种能力,得靠外部脚本 (monit、supervisor) 补。
所以 systemd 出现了。它是现代的 init 系统 + 服务管理器,特点归纳成一句话:并行启动、统一配置、自带日志、自带监控。
ps -p 1 -o pid,comm,args # 看看 PID 1 是谁
# PID COMMAND ARGS
# 1 systemd /sbin/init
提示 检查 PID 1 就能判断系统用的是不是 systemd。
systemctl --version还能看到它的具体版本,这台服务器跑的是 255 系列,Ubuntu 24.04 标配。
systemd 是"由谁在管谁"的架构¶
Systemd 用编号命名的一套配置段来描述每个后台任务。它管的不只是服务,而是一整类单元。你可以把 systemd 想成一栋楼的物业:
| systemd 概念 | 楼里的角色 | 生活中对应 |
|---|---|---|
| unit 文件 | 每套房的管理登记表 | /etc/systemd/system/xxxx.service |
| 服务 (service) | 一套常驻的房间 | node server.js、nginx |
| 定时器 (timer) | 定好钟点来查房 | cron 的 systemd 版 |
| target | 目标状态 | multi-user.target(多用户模式) |
| journal | 每套房的事件记录本 | 日志,统一由 journald 写 |
Systemd 的核心是一个叫 systemd(作为 PID 1) 的守护进程,配合 journald(写日志)、systemctl(命令行)、systemd-analyze(诊断启动时间)等工具一起工作。
Unit:一切皆是单元¶
在 systemd 里,每一种"可被管理的对象"都是一个 unit(单元),用 type.后缀 命名。后缀决定了它是哪种单元:
| 后缀 | 含义 | 典型场景 |
|---|---|---|
.service |
后台服务进程 | node API、nginx、mysql 服务 |
.target |
一组单元的集合/目标状态 | multi-user.target |
.timer |
定时触发某个 unit | 替代 cron 的定时任务 |
.socket |
监听端口,激活时才起服务 | socket 激活的 Web 服务 |
.mount / .automount |
挂载点 | 磁盘分区挂载 |
.path |
文件/目录变化时触发 | 监控某个文件出现 |
.slice |
资源分组 | 按 CPU/内存分组配额 |
systemctl list-units --type=service --all # 列出所有 service 单元
systemctl list-unit-files # 列出所有 unit 文件 + 是否开机启用
Target:把"开机要启动什么"聚合成目标¶
multi-user.target 是这里频繁出现的一个词。它不是一个服务,而是一个目标状态:代表"多用户模式下该有的那堆服务都在跑"。把一个服务的 [Install] WantedBy=multi-user.target 配好,就等于告诉 systemd:"进入多用户模式时把我也带上"。
systemctl list-dependencies multi-user.target # 看这个 target 会拉起哪些服务
你在这台服务器上会看到 bangdream.service、dsh.service 等,它们的 [Install] WantedBy=multi-user.target,这正是"重启机器后自动恢复服务"的神秘来源——第 4 章细讲。
本服务器上的 systemd 规模¶
这台机器上不仅跑了业务服务,还跑了一堆系统组件,列出几个有代表性的:
| 服务 | 干什么的 |
|---|---|
bangdream / lovelive |
两个 Node 角色数据库 API,监听 3000 段端口 |
dsh |
DeepSeek Harness Web 界面 |
dsh-auth-proxy |
GitHub OAuth 鉴权代理 |
xray |
代理隧道,以 nobody 低权限跑 |
rustdesk-hbbs / hbbr |
远程桌面中继/ID 服务 |
prometheus / prometheus-node-exporter |
性能监控采集 + 导出器 |
mysql |
数据库 |
它们有的是 node 写的,有的是打包好的二进制,但都靠同一套 systemd 规则管理——这正是这章的书名"统一管理"的意义。
从哪里查信息:三条只读命令¶
刚接触 systemd,先掌握三条绝不改状态的查询命令,怎么敲都不会把服务搞坏:
systemctl status bangdream.service # 单个服务的详细状态
systemctl list-units --type=service # 当前活动(active)的服务
systemctl list-unit-files # 所有 unit 文件及其开机状态
status 是最常用的一条,它一次告诉你:是否在跑、PID、内存、CPU、最近日志、以及这段 node server.js 到底是谁在跑。
注意
status、list-units、list-unit-files都是只读的,随便看。但start/stop/restart会真正改动服务状态,一开始别乱敲,先看清楚要动哪个再动。第 2 章专门讲怎么正确地改。
易错点¶
systemctl不等于service:service nginx restart是老式兼容命令,新项目的脚本里优先用systemctl。- 改了 unit 文件必须
daemon-reload:否则 systemd 读的还是内存里的旧配置,你改的字段不生效。这在第 3 章会反复强调。 - 区分"没启用"和"没运行":
disable(开机不启动) 和stop(现在不跑) 是两个独立概念,别混。 - root 才能管理服务:普通用户敲
systemctl start xxx会报Access denied,要么用sudo,要么配置sudoers。
相关命令¶
systemctl(全家桶)、systemd-analyze(分析启动耗时)、systemd-cgls(看 cgroup 树)、ps -p 1(确认 PID 1)、systemctl --version(看版本)。