systemd 服务管理与日志查看实战

目录

systemctl 和 journalctl 是 Linux 上每天都会用到的两个命令,但很多人只会 systemctl restart nginx 和 journalctl -u nginx -f 这种最浅的用法。一旦遇到「服务起不来」「日志被清了」「配置改了没生效」这种问题,就开始抓瞎。

这篇把这两个命令的关键机制和真正常用的姿势讲清楚。

一、systemd 服务的目录优先级

最容易踩坑的地方就是单元文件可以放在多个目录里,谁覆盖谁有讲究。

优先级 目录路径 说明
最高 /etc/systemd/system/ 本地管理员自定义或覆盖的单元文件
中 /run/systemd/system/ 运行时动态生成的单元
低 /usr/lib/systemd/system/ 软件包安装提供的默认单元(现代发行版主流)
低 /lib/systemd/system/ 旧路径,通常是上一个的符号链接
低 /usr/local/lib/systemd/system/ 本地手动安装的单元

查看一个完整的搜索路径列表:

systemd-analyze unit-paths

⚠️ 永远不要直接改 /usr/lib/systemd/system/ 里的文件——它属于软件包,下次升级就被覆盖。要改用下面的 Drop-in 机制。

二、Drop-in:局部覆盖单元配置的正确姿势

systemd 加载单元时,会自动扫描 <单元名>.d/ 目录下的 .conf,按优先级合并进主配置——这就是 Drop-in 机制。

流程图流程图

最佳实践:用 systemctl edit 让 systemd 帮你自动建覆盖文件:

sudo systemctl edit nginx.service
# 自动在 /etc/systemd/system/nginx.service.d/override.conf 创建编辑窗口

写完保存,systemd 会 daemon-reload,下次启动就生效。改完原单元文件必须手动 reload:

sudo systemctl daemon-reload

三、systemctl 高频命令速查

命令 含义
systemctl status <unit> 查看服务详细状态
systemctl start <unit> 立即启动
systemctl stop <unit> 立即停止
systemctl restart <unit> 重启(先停再启)
systemctl reload <unit> 重新加载配置(不中断,需服务支持)
systemctl enable <unit> 设置开机自启
systemctl disable <unit> 取消开机自启
systemctl is-enabled <unit> 查询是否开机自启
systemctl is-active <unit> 查询是否正在运行
systemctl list-units --type=service 列出所有服务单元
systemctl list-unit-files --type=service 列出所有服务文件 + 启用状态
systemctl daemon-reload 重新加载所有单元文件
systemctl edit <unit> 创建 Drop-in 覆盖配置
systemctl cat <unit> 查看完整生效配置(含覆盖)
systemctl show -P FragmentPath <unit> 查这个单元真正加载的是哪个文件

3.1 只看正在运行的服务

systemctl list-units --type=service --state=running

3.2 排查“我改的配置到底有没有生效”

# 看真实加载的是哪个文件
systemctl show -P FragmentPath nginx.service

# 看合并后的最终内容
systemctl cat nginx.service

🪤 经典坑:在 /etc/systemd/system/ 写了同名 .service 但忘了 daemon-reload,systemd 还在用旧文件,怎么 restart 都没用。

四、journalctl:systemd 日志的查询入口

systemd 把日志统一收到 journald,由 journalctl 查询。先理解 3 个概念:

概念 说明
systemd-journald 后台服务,负责收集日志(来源:内核、服务 stdout/stderr、syslog 转发等)
journal 日志数据库(结构化),位于 /run/log/journal/(内存)或 /var/log/journal/(持久化)
journalctl 用户态查询/过滤/导出命令

4.1 基础查询

# 查全部(默认分页)
journalctl

# 不分页直接输出
journalctl --no-pager

# 最近 N 行
journalctl -n 100

# 实时跟随(像 tail -f)
journalctl -f

4.2 按服务过滤

最常用的姿势,调试某个服务起不来:

journalctl -u nginx
journalctl -u nginx -n 200
journalctl -u nginx -f

4.3 按启动会话过滤

# 本次启动以来的日志
journalctl -b

# 上一次启动的日志(比如刚刚崩了想看上次的)
journalctl -b -1

# 列出所有启动会话
journalctl --list-boots

4.4 按时间过滤

journalctl --since today
journalctl --since yesterday
journalctl --since "10 min ago"
journalctl --since "1 hour ago"
journalctl --since "2026-06-01 09:00:00" --until "2026-06-01 10:00:00"

4.5 按日志级别过滤

journalctl -p err        # 仅错误
journalctl -p warning    # 警告及以上
journalctl -p info       # info 及以上

优先级从低到高:debug → info → notice → warning → err → crit → alert → emerg。

4.6 按进程 / 用户过滤

# 按 PID
journalctl _PID=1234

# 当前用户的用户服务日志
journalctl --user
journalctl --user -u myservice

五、日志占用与清理

很多服务器跑久了 /var/log/journal/ 能吃掉几个 G:

# 看占用
journalctl --disk-usage

# 按大小清理到 200MB
sudo journalctl --vacuum-size=200M

# 按时间清理(保留 7 天)
sudo journalctl --vacuum-time=7d

# 按文件数清理
sudo journalctl --vacuum-files=5

可以放进 cron 或 systemd timer 里定时跑。

六、持久化日志:默认可能没开

🪤 重启后日志没了? 大概率是 journald 只存内存——/var/log/journal/ 不存在。

检查:

ls /var/log/journal/ 2>/dev/null || echo "未持久化"

启用持久化,编辑 /etc/systemd/journald.conf:

[Journal]
Storage=persistent
SystemMaxUse=500M
SystemKeepFree=1G
配置项 含义
Storage=persistent 强制写到磁盘
Storage=auto(默认) 有 /var/log/journal/ 就持久化,没有就内存
SystemMaxUse=500M journal 最多占 500MB
SystemKeepFree=1G 磁盘至少留 1GB 给其它用途

改完重启 journald:

sudo systemctl restart systemd-journald

七、组合姿势:调试服务“启不来”的标准流程

新装一个服务跑不起来时,按这个顺序排查:

流程图流程图

实际命令组合:

# 1. 看状态
systemctl status nginx

# 2. 看最近 100 行日志
journalctl -u nginx -n 100

# 3. 实时跟着 + 手动重启
journalctl -u nginx -f &
systemctl restart nginx

# 4. 实在不行,直接前台跑 ExecStart
systemctl cat nginx     # 找到 ExecStart=/usr/sbin/nginx -g 'daemon off;'
/usr/sbin/nginx -g 'daemon off;'   # 直接跑,看错误输出

八、几条实用经验

  • 改配置必 daemon-reload:单元文件改完不 reload 等于没改。
  • 不要直接改 /usr/lib/systemd/system/ 下的文件,用 systemctl edit 创 Drop-in。
  • 生产服务 enable 一定要带 --now:systemctl enable --now nginx 等于 enable + start,少打一条命令。
  • journalctl -u xxx -f 是调试新服务最高效的方式,开一个终端常驻。
  • journal 太大别全删,按 --vacuum-time=30d 保留近期的就好。

掌握这套,绝大多数 Linux 服务相关的问题都能 5 分钟定位。