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=running3.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 -f4.2 按服务过滤
最常用的姿势,调试某个服务起不来:
journalctl -u nginxjournalctl -u nginx -n 200journalctl -u nginx -f4.3 按启动会话过滤
# 本次启动以来的日志journalctl -b
# 上一次启动的日志(比如刚刚崩了想看上次的)journalctl -b -1
# 列出所有启动会话journalctl --list-boots4.4 按时间过滤
journalctl --since todayjournalctl --since yesterdayjournalctl --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 按进程 / 用户过滤
# 按 PIDjournalctl _PID=1234
# 当前用户的用户服务日志journalctl --userjournalctl --user -u myservice五、日志占用与清理
很多服务器跑久了 /var/log/journal/ 能吃掉几个 G:
# 看占用journalctl --disk-usage
# 按大小清理到 200MBsudo 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=persistentSystemMaxUse=500MSystemKeepFree=1G| 配置项 | 含义 |
|---|---|
Storage=persistent | 强制写到磁盘 |
Storage=auto(默认) | 有 /var/log/journal/ 就持久化,没有就内存 |
SystemMaxUse=500M | journal 最多占 500MB |
SystemKeepFree=1G | 磁盘至少留 1GB 给其它用途 |
改完重启 journald:
sudo systemctl restart systemd-journald七、组合姿势:调试服务”启不来”的标准流程
新装一个服务跑不起来时,按这个顺序排查:
检查 ExecStart 路径] C --> E{看到什么错误?} E -->|端口占用| F[ss -lntp grep 端口] E -->|文件找不到| G[检查路径权限] E -->|配置语法| H[直接前台跑命令复现] D --> I[手动跑 ExecStart 看输出]
实际命令组合:
# 1. 看状态systemctl status nginx
# 2. 看最近 100 行日志journalctl -u nginx -n 100
# 3. 实时跟着 + 手动重启journalctl -u nginx -f &systemctl restart nginx
# 4. 实在不行,直接前台跑 ExecStartsystemctl 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 分钟定位。