结构
unit 把服务的运行方式交给 systemd
网站服务器、定时任务调度器都需要在后台持续工作。把程序放到后台只是第一步:它还需要在机器启动后运行、退出后被察觉,并留下可查询的记录。systemd 是 Ubuntu 的系统与服务管理器;在正常启动的 Ubuntu 主机上,它是进程编号(PID)为 1 的用户态进程。
管理器把被管理的对象称为单元(unit),其中 .service 单元描述如何运行一项服务。unit 文件是分节的纯文本配置:它写清程序路径、用户、工作目录、环境变量和重启策略。systemctl 是向管理器查询状态或发送请求的命令。
本页操作面向以 systemd 为 PID 1 的 Ubuntu 虚拟机或云主机。普通 ubuntu:26.04 Docker 容器通常直接启动 Shell,没有完整的系统管理器;容器里出现“未以 systemd 启动”类错误,应先确认运行环境。
先看一个只负责等待的服务
本页用自建的 demo.service 贯穿观察。它只运行 /usr/bin/sleep infinity,持续等待,便于看清管理机制。下面是实际使用的配置,不是 Ubuntu 自带服务。
[Unit]
Description=Learning demo service
[Service]
Type=exec
User=service-demo
WorkingDirectory=/tmp
Environment=DEMO_MODE=learning
ExecStart=/usr/bin/sleep infinity
Restart=on-failure
RestartSec=2s
[Install]
WantedBy=multi-user.target
- [Unit]:它叫什么
Description是说明文字;这里也能写与其他单元的依赖关系。- [Service]:它怎么运行
Type=exec在程序成功执行后报告启动成功。User指定运行身份;WorkingDirectory、Environment明确环境;ExecStart指定程序和参数。- Restart:退出后如何处理
on-failure表示失败后尝试重启,RestartSec设置等待时间。主动stop不会触发这种重启;连续失败还可能遇到启动频率限制。- [Install]:自启时挂到哪里
multi-user.target是一个组织系统启动依赖的目标单元。这里声明启用时的关联;单写这一行不会自动启用服务。
服务进程由管理器启动,不能假定它继承你当前终端的 export、工作目录或虚拟环境。终端能跑、服务不能跑时,回看环境变量与工作目录,通常比反复重启更有用。
你在终端里 export 了一个变量,随后 systemctl 启动服务。服务一定能读到它吗?
环境沿进程启动关系传递,不是整台机器共享的公告栏。systemctl 向管理器发请求;真正启动服务的是管理器。要交付稳定的环境,应在服务配置中明确所需的目录、变量与程序路径。
深入一点:后台进程与 service unit 并不完全等同
本页以常驻服务为主。systemd 也能管理执行完就退出的一次性服务(Type=oneshot),还管理 .socket、.timer、.mount 等单元。用户自己的服务由另一套用户管理器管理,常用 systemctl --user;它与本页的系统服务范围不同。
观察与操作
Active 看现在,enabled 看启动关联
先执行 systemctl status demo.service,看管理器有没有读到配置、进程是否在跑。status 还会附上最近几条日志;它是一张概览,完整的时间线要去 journal 查。
以下为 Ubuntu 26.04 Minimal Cloud Image 的 QEMU 虚拟机实测,字段会随机器、时间和版本变化。为便于对照,省去 Invocation、资源统计与末尾的最近日志行。
- Loaded
- 配置是否载入,以及从哪个文件载入。
loaded是已读到配置;not-found则先核对服务名和文件路径。 - disabled
- 尚未通过 enable 建立启动关联。同一行的
preset是发行版或管理员提供的预设策略,不是当前运行状态。 - Active
- 此刻的单元状态与更细的子状态。本例
active (running)表示正在运行;inactive是未活动;failed要继续查失败原因。 - Main PID
- 服务主进程的编号及名称。它与管理器的 PID 1 不同;重启服务后主进程编号可能变化。
- CGroup
- 这项服务归属的进程组路径。cgroup 是内核给进程分组、统计和限制资源的机制,下面列出该组中的进程。
运行状态和启动关联互不等价。刚才用 start 启动了服务,所以它可以是 active,同时仍是 disabled。反过来,已启用的服务也可能启动失败;enable 不代表程序健康。
| 你要做什么 | 命令(以 demo 为例) | 影响哪个维度 |
|---|---|---|
| 看状态 | systemctl status demo.service | 只观察 |
| 现在启动 | sudo systemctl start demo.service | 当前运行;不设置自启 |
| 现在停止 | sudo systemctl stop demo.service | 当前运行;不取消自启 |
| 停下再启动 | sudo systemctl restart demo.service | 当前运行;会打断服务 |
| 设为开机自启 | sudo systemctl enable demo.service | 启动关联;不立即启动 |
| 取消开机自启 | sudo systemctl disable demo.service | 启动关联;不立即停止 |
这些修改状态的命令建议只对虚拟机里的 demo 服务试。想同时“启用并立即启动”,可用 sudo systemctl enable --now demo.service。普通用户通常能查看状态,修改系统服务则需要管理员权限。
按直接改变的维度分类,不考虑附加的 --now 选项。
- start
- enable
- restart
- disable
- stop
start、stop、restart 管现在;enable、disable 管启动依赖的关联。拆开这两个维度,才能解释“在跑但未自启”和“已自启但失败”。
一个服务已 enabled,刚被你 stop。希望它现在恢复运行,并保留原来的自启设置,应该选什么?
enable 只处理启动关联,不会单独启动服务。
disable 会取消关联,却不能恢复当前进程。
start 请求管理器现在启动这项服务,不改已有的 enabled 设置。这里无需重新设置自启,也无需重启整台机器。
深入一点:disabled 也不等于绝对不会自动启动
服务还可能被其他单元依赖、定时器或套接字触发。static 通常表示没有可直接 enable 的安装信息;masked 则阻止启动。遇到这些状态,先读 unit 的关系,不把 enable 当作通用修复。
日志
journal 按服务查,文本日志按路径查
systemd-journald 是收集日志的服务,journal 是它保存的结构化日志库,journalctl 是查询工具。服务交给管理器的标准输出和标准错误通常进入 journal;服务也可以配置为写自己的文件。
先把范围缩到同一项服务
-u demo.service 按单元筛选;-b 限定本次开机;-n 30 看最近 30 条。这样你不会在整台机器的日志里找同一处错误。
-f 持续跟随新日志。可以在另一个终端重现问题,再回来看新增记录;按 Ctrl+C 结束跟随,只会退出查看器,不会停止服务。
日志可能包含多个进程和多次启动。读时间、服务名、PID,再找失败附近的第一条具体报错,不只看最后一句“启动失败”。
上面只摘录一次成功启动的两条日志;sleep 本身不输出内容,记录来自管理器。下面的失败实验会产生更具体的错误。若普通用户看到权限提示或记录不全,而你有这台机器的管理权限,可用 sudo journalctl 重查。交互分页器用 q 退出;加 --no-pager 则直接打印,方便交给 AI 一起分析。
| /var/log 中的线索 | 谁写、怎么看 |
|---|---|
journal/ | journal 的持久化存储(若启用);用 journalctl,不要当普通文本读。 |
apt/history.log、dpkg.log | 软件安装与包管理历史;调查“升级后才坏了”时有帮助。 |
syslog、auth.log | 安装并配置 rsyslog 等日志系统时可能存在;不是所有 Ubuntu 镜像都会生成。 |
| 应用专属目录 | 例如安装 nginx 后按其配置生成的 nginx/;用 less 查看,路径与内容以应用配置为准。 |
文件日志可能轮转成 .1 或 .gz:旧内容移到归档,新文件继续写。less /var/log/dpkg.log 可看文本,压缩归档可用 zless。缺一个熟悉的文件名不等于系统没有日志。
你要按 demo.service 筛选并持续跟随 journal。补上两个选项(上方可查)。
journalctl demo.service
-u 选服务,-f 跟随;先缩小对象,再观察变化。退出跟随与停止服务是两件事。
排障流程
先找失败证据,再改对应的运行环境
服务起不来时,先记住失败发生在哪一次启动。下面把同一个 demo 服务的排查展开:从管理器是否就绪,到 unit、日志与实际环境,逐层缩小范围。
- 确认命令连的是预期的主机。用
ps -p 1 -o comm=看 PID 1;若不是 systemd,先回到 Ubuntu 虚拟机或主机。管理器在运行后,下一步先重启,还是先取状态? - 执行
systemctl status demo.service --no-pager --full。先区分未找到配置、未活动、启动失败;记下退出原因。失败服务的 status 返回非零退出码是正常的查询结果。 - 执行
journalctl -u demo.service -b -n 30 --no-pager。读失败附近的具体错误;若日志权限不足,有管理权限时加 sudo。如果日志指向“无法切换工作目录”,应该检查哪个配置项? - 用
systemctl cat demo.service看文件与覆盖配置。对照WorkingDirectory、User、ExecStart、环境变量和文件权限;目录存在也不代表服务用户能进入。 - 若改了 unit,先
sudo systemctl daemon-reload让管理器重读,再sudo systemctl restart demo.service。若只改应用配置,按应用文档选择 reload 或 restart;daemon-reload 本身不重启服务。 - 重新取 status 与本次的新日志,并验证实际功能。若进程已在跑但访问失败,转到网络与资源排查;active 不保证端口、磁盘、内存与业务都正常。
实测一个“工作目录不存在”的失败
在实验虚拟机中,把 demo 的 WorkingDirectory 临时改成 /no-such-service-directory,重读 unit 后重启,就能观察到下面的结果。建议只对这个实验服务操作;修复时把目录恢复为 /tmp,再次重读并重启。
CHDIR 指“切换目录”这一步。上面只摘录失败附近的四条记录。程序还没正常开始工作,就已在准备运行环境时失败。此时 enable 不会创建目录,反复 restart 也不会修复路径;应对照日志修改目录或权限。
你修正了 unit 中的 WorkingDirectory,文件已保存。要让管理器使用新定义并重新运行,哪一组操作合适?
enable 设置启动关联,不负责重读并执行新的运行定义。
daemon-reload 重读定义,但不会把已有进程换成新进程。
文件、管理器读入的定义、正在运行的进程是三层状态。保存修改后,重读定义,再重新启动进程,最后用状态和新日志验证,才算完成一次修复。
深入一点:频繁失败、权限与清理实验
若连续失败后遇到启动频率限制,先修正根因,再用 sudo systemctl reset-failed demo.service 清除失败记录及相关计数,然后启动。不要用无限重试替代诊断。
本例创建了专用的 service-demo 系统用户,不允许交互登录。真实应用也应使用专用服务用户,赋予需要的目录访问权,避免为了排障直接全部改成 root。
实验结束可依次执行 sudo systemctl disable --now demo.service、sudo rm /etc/systemd/system/demo.service、sudo systemctl daemon-reload。然后用 sudo userdel service-demo 删除本页新增的实验用户。这会停止并删除服务定义,历史日志仍按保留策略保存。
随手速查
用状态找入口,用日志解释原因
- systemd 按 unit 管进程;服务的用户、目录、变量要明确。
- status 先看 Loaded,再看 Active、Main PID 与失败原因。
- start / stop 管现在,enable / disable 管启动关联。
- journalctl -u 选服务,-f 跟随新日志;/var/log 还可能有应用与包管理文本日志。
- 改 unit 后 daemon-reload,再重新启动并验证;进程在跑后仍需检查功能。
准备请 AI 协助排查“终端能运行、服务失败”。你会交给它哪些证据?用两句话写下来。
提供 status、失败附近同一服务的 journal、systemctl cat 的配置,以及终端与服务在用户、目录、环境变量上的差异。附上最近修改和复现时间,才能把“环境不一样”变成可核对的原因;分享前去掉 token、密码等凭据。
- 有服务名、时间与具体失败日志
- 有 unit 配置与运行环境的对照
- 有修改记录与验证结果
本页依据与实测记录
截至 2026-11-06,Ubuntu 26.04 LTS。命令语义以该版本手册为准;本页终端输出取自独立 QEMU 虚拟机,省略行在记录外说明,不补造输出。服务配置为本页自建实验。
- systemd(1) · Ubuntu 26.04:PID 1、系统管理器与用户管理器。
- systemctl(1) · Ubuntu 26.04:status 字段、start、stop、enable、daemon-reload 与 reset-failed。
- systemd.unit(5) 与 systemd.service(5):单元路径、安装关联与重启策略。
- systemd.exec(5):用户、工作目录、环境、输出与 CHDIR 退出状态。
- journalctl(1) 与 systemd-journald(8):按单元过滤、跟随、读取权限与保存路径。
- Ubuntu · Viewing and monitoring log files:文件日志、应用日志与 less。文件名示例应结合本机安装情况核对。
- dpkg(1):包管理日志
/var/log/dpkg.log。其余文件是否出现取决于镜像中安装的软件与配置。 - Ubuntu 26.04 Minimal Cloud Image · 20261105:实测镜像;QEMU TCG,2 个虚拟 CPU、1 GiB 内存;镜像报告 Ubuntu 26.04.1 LTS,systemd 259.9-0ubuntu0.1。按上文创建 demo,实测启动、停止、重启、启用、取消启用、状态查询、日志跟随与目录失败、修复。