883 字
4 分钟
systemd 服务管理与 journalctl 日志排查入门

现代主流发行版(Ubuntu 16.04+、Debian 8+、RHEL/CentOS 7+、Fedora)都用 systemd 做初始化系统。日常打交道最多的是两件事:用 systemctl 管服务,用 journalctl 看日志。本文再进一步:写一个自己的 unit 文件,把脚本变成受管服务。

systemctl 日常操作速查#

Terminal window
systemctl status nginx # 状态 + 最近几行日志
sudo systemctl start nginx # 启动
sudo systemctl stop nginx # 停止
sudo systemctl restart nginx # 重启
sudo systemctl reload nginx # 重载配置(进程不中断,需服务支持)
sudo systemctl enable nginx # 开机自启(不改当前状态)
sudo systemctl enable --now nginx # 自启 + 立即启动
sudo systemctl disable --now nginx # 取消自启并停止

status 输出里最值钱的两行:Active: active (running) since ... 和 Main PID。如果看到 failed,先别急着 restart——失败原因往往就在 status 显示的最近日志里。

几个容易混淆的点:

  • enable 只管开机自启,不影响当前运行状态;--now 把两件事一起做。
  • reload 依赖服务自己支持(ExecReload),不支持时会报错,这时只能用 restart。
  • systemctl is-active nginx、is-enabled、is-failed 返回简单状态,适合写脚本判断。

看懂 unit 文件#

unit 文件通常在 /etc/systemd/system/(自定义)和 /usr/lib/systemd/system/(软件包安装)下。systemctl cat nginx 能直接查看。

一个最小可用的自定义服务,把 /opt/myapp/run.sh 变成服务:

[Unit]
Description=My App
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/run.sh
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

三个段落的分工:

  • [Unit]:元信息和启动顺序。After=network-online.target 保证网络就绪后再启动——依赖网络的服务只写 network.target 是不够的。
  • [Service]:怎么跑。Type=simple 表示 ExecStart 的进程就是主进程;Restart=on-failure 异常退出时自动拉起;User= 让服务以非 root 身份运行,是安全基线。
  • [Install]:何时被启用。WantedBy=multi-user.target 表示 enable 后随正常多用户模式启动。

改完 unit 文件必须执行 sudo systemctl daemon-reload 让 systemd 重新读取,然后 sudo systemctl enable --now myapp。

journalctl:结构化日志的正确用法#

systemd 把服务标准输出、错误输出和内核日志统一收进 journal。基本用法:

Terminal window
journalctl -u myapp # 某个服务的全部日志
journalctl -u myapp -n 200 # 最近 200 行
journalctl -u myapp -f # 实时跟踪(类似 tail -f)
journalctl -u myapp --since "1 hour ago"
journalctl -u myapp --since "2026-09-12 20:00" --until "2026-09-12 21:00"
journalctl -p err # 只看 err 及以上优先级(所有服务)
journalctl -k # 内核日志(等价 dmesg)
journalctl -b # 本次开机以来的日志
journalctl --disk-usage # 日志占了多少磁盘

两个实用技巧:

  • -o json-pretty 输出完整结构化字段,能看到 _PID、_EXE 等元数据,写日志收集脚本时用得上。
  • -x 给部分日志附加解释文字(如 OOM、core dump),排障时值得一看。

排查套路:服务起不来怎么办#

  1. systemctl status myapp:看退出码和最后几行输出。
  2. journalctl -u myapp -n 100 --no-pager:看完整错误。
  3. 常见根因对号入座:
    • status=203/EXEC:ExecStart 路径错误或文件不可执行;
    • status=217/USER:User= 指定的用户不存在;
    • code=exited, status=1:程序自己报错,去读程序日志;
    • 权限问题:检查 WorkingDirectory、日志目录对 User= 是否可写。
  4. 修复后 daemon-reload(改了 unit 才需要)→ reset-failed → start。

journal 默认持久化程度因发行版而异:/var/log/journal/ 存在才持久,否则重启即丢。生产机器建议确认 Storage=persistent(/etc/systemd/journald.conf),并用 SystemMaxUse= 限制体积。

延伸阅读#

systemd 服务管理与 journalctl 日志排查入门
https://meow.us.kg/posts/systemd-unit-journalctl-guide/
作者
もゆちゃん
发布于
2026-09-12
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取