systemd 是现代 Linux 发行版中最主流的初始化系统和服务管理器,它用统一的概念——Unit(单元)——来管理系统的各个部分。每个 Unit 对应一个由配置文件描述的实体,这些配置文件统称为 Unit 文件,通常位于 /lib/systemd/system/(系统软件包提供)和 /etc/systemd/system/(系统管理员自定义,优先级更高)。
1. Unit 文件类型
Unit 的类型由文件扩展名标识,最常见的包括:
| 扩展名 | 类型 | 用途 |
|--------|------|------|
| .service | 服务单元 | 定义一个系统服务(如 nginx、sshd)以及如何启动、停止和管理它 |
| .socket | 套接字单元 | 封装一个本地 IPC 或网络套接字,用于基于套接字的激活(systemd 先监听套接字,等有连接时再启动对应服务) |
| .target | 目标单元 | 类似于旧式 SysV 的运行级别(multi-user.target 相当于运行级别 3,graphical.target 相当于运行级别 5),用于将一组 Unit 组织成一个同步点 |
| .mount | 挂载单元 | 定义文件系统的挂载点,实现挂载管理的自动化(会根据挂载路径生成文件名,如 - 替换 /) |
| .timer | 定时器单元 | 替代 cron 作业,以更灵活的方式定义定时触发的任务 |
| .device | 设备单元 | 由 systemd 动态生成,代表内核识别到的硬件设备,供依赖管理使用 |
| .slice | 切片单元 | 用于以分层方式对资源(CPU、内存等)进行分组和控制,实现精细化的资源限制 |
2. 一个典型的 Service Unit 文件格式
每个 Unit 文件的语法类似 INI 格式,由若干 [段] 组成,常用的有 [Unit]、[Service](仅 service 类型有)和 [Install]。下面是一个简化但实用的示例 /etc/systemd/system/myapp.service:
[Unit]
Description=我的自定义应用
After=network.target # 在网络就绪之后再启动该服务
Wants=postgresql.service # 弱依赖:如果可以,就同时启动 PostgreSQL
[Service]
Type=simple # 服务进程不会 fork,主进程就是服务进程
ExecStart=/usr/local/bin/myapp --config /etc/myapp.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure # 仅当进程退出码不为0或被信号终止时自动重启
User=myappuser
Group=myappgroup
WorkingDirectory=/var/lib/myapp
Environment="LANG=zh_CN.UTF-8"
[Install]
WantedBy=multi-user.target # 使服务在系统进入多用户模式时被启动
关键字段说明:
After=...定义了启动顺序的先后关系,但不影响依赖本身(如果希望强制依赖,应使用Requires=)。Type=指定服务启动类型,常见的有simple(默认,主进程即为服务)、forking(服务会 fork 一次子进程,父进程退出)、oneshot(一次性任务)、notify(服务启动完成后会发送通知)等。ExecStart=是启动服务的命令,必须是绝对路径。Restart=控制何时自动重启服务,常用值有always、on-failure、on-abnormal等。WantedBy=定义了该 Unit 应被哪个 target 所“想要”(弱依赖),当启用服务(systemctl enable)时,会在对应 target 的目录下创建软链接。
3. 查看与编写 Unit 文件的实际流程
- 列出已安装的所有 Unit:
systemctl list-unit-files - 查看某 Unit 的完整状态和最近日志:
systemctl status myapp.service - 查看 Unit 文件的原始内容:
systemctl cat myapp.service(会显示所有相关片段及覆盖文件) - 编辑某个 Unit 的配置片段(推荐方式):
sudo systemctl edit myapp.service(会创建一个 override 文件,而不是直接修改原始文件) - 完整编辑整个 Unit 文件:直接创建或修改
/etc/systemd/system/myapp.service,然后执行sudo systemctl daemon-reload(重新加载配置)和sudo systemctl restart myapp(重启服务)
4. 格式与调试要点
- 等号(
=)两边不能有空格,否则会被视为错语格式。 - 以
#或;开头的行为注释行。 - 可以用
EnvironmentFile=引入外部环境变量文件,便于集中管理配置。 - 如果某一项有多个值,可以使用空格分隔,例如
After=network.target postgresql.service。 - 启动失败时,先检查日志:
journalctl -u myapp.service -xe,它往往能直接告诉你ExecStart=里的路径是否存在、权限是否正确、Type=设置是否与实际行为匹配等。
Unit 文件格式看似简单,但通过 [Install] 的依赖关系和 [Service] 的细粒度控制,可以非常灵活地表达复杂的启动逻辑、依赖顺序和资源限制。掌握这一基础,就能够自建久经考验的现代服务管理配置,极大提升 Linux 系统的维护效率。