Daimon's Blog
主页 归档 关于 RSS 探针 常用工具
主页
归档
关于
RSS
探针
常用工具

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

daimon daimon 2026-04-28 #Linux#systemd#systemctl#journalctl

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/本地手动安装的单元

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

Terminal window
1
systemd-analyze unit-paths

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

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

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

graph TD A[加载 nginx.service 主文件] --> B[扫描 /etc/systemd/system/nginx.service.d/*.conf] B --> C[扫描 /run/systemd/system/nginx.service.d/*.conf] C --> D[扫描 /usr/lib/systemd/system/nginx.service.d/*.conf] D --> E[按优先级合并
后面覆盖前面]

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

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

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

Terminal window
1
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 只看正在运行的服务#

Terminal window
1
systemctl list-units --type=service --state=running

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

Terminal window
1
# 看真实加载的是哪个文件
2
systemctl show -P FragmentPath nginx.service
3
4
# 看合并后的最终内容
5
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 基础查询#

Terminal window
1
# 查全部(默认分页)
2
journalctl
3
4
# 不分页直接输出
5
journalctl --no-pager
6
7
# 最近 N 行
8
journalctl -n 100
9
10
# 实时跟随(像 tail -f)
11
journalctl -f

4.2 按服务过滤#

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

Terminal window
1
journalctl -u nginx
2
journalctl -u nginx -n 200
3
journalctl -u nginx -f

4.3 按启动会话过滤#

Terminal window
1
# 本次启动以来的日志
2
journalctl -b
3
4
# 上一次启动的日志(比如刚刚崩了想看上次的)
5
journalctl -b -1
6
7
# 列出所有启动会话
8
journalctl --list-boots

4.4 按时间过滤#

Terminal window
1
journalctl --since today
2
journalctl --since yesterday
3
journalctl --since "10 min ago"
4
journalctl --since "1 hour ago"
5
journalctl --since "2026-06-01 09:00:00" --until "2026-06-01 10:00:00"

4.5 按日志级别过滤#

Terminal window
1
journalctl -p err # 仅错误
2
journalctl -p warning # 警告及以上
3
journalctl -p info # info 及以上

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

4.6 按进程 / 用户过滤#

Terminal window
1
# 按 PID
2
journalctl _PID=1234
3
4
# 当前用户的用户服务日志
5
journalctl --user
6
journalctl --user -u myservice

五、日志占用与清理#

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

Terminal window
1
# 看占用
2
journalctl --disk-usage
3
4
# 按大小清理到 200MB
5
sudo journalctl --vacuum-size=200M
6
7
# 按时间清理(保留 7 天)
8
sudo journalctl --vacuum-time=7d
9
10
# 按文件数清理
11
sudo journalctl --vacuum-files=5

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

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

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

检查:

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

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

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

改完重启 journald:

Terminal window
1
sudo systemctl restart systemd-journald

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

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

graph TD A[systemctl status xxx] --> B{有错误吗?} B -->|是| C[journalctl -u xxx -n 100] B -->|否但没运行| D[systemctl cat xxx
检查 ExecStart 路径] C --> E{看到什么错误?} E -->|端口占用| F[ss -lntp grep 端口] E -->|文件找不到| G[检查路径权限] E -->|配置语法| H[直接前台跑命令复现] D --> I[手动跑 ExecStart 看输出]

实际命令组合:

Terminal window
1
# 1. 看状态
2
systemctl status nginx
3
4
# 2. 看最近 100 行日志
5
journalctl -u nginx -n 100
6
7
# 3. 实时跟着 + 手动重启
8
journalctl -u nginx -f &
9
systemctl restart nginx
10
11
# 4. 实在不行,直接前台跑 ExecStart
12
systemctl cat nginx # 找到 ExecStart=/usr/sbin/nginx -g 'daemon off;'
13
/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 分钟定位。

Linux 防火墙三国杀:ufw / firewalld / iptables / nftables 怎么选
Linux 包管理器横评:apt / dnf / pacman / nix / flatpak / snap / appimage
本博客所有文章除特别声明外,均遵循 CC BY-NC-SA 4.0 协议,转载请注明出处。
博客框架 Astro & Fuwari
冀ICP备20260167号
1
一、systemd 服务的目录优先级
2
二、Drop-in:局部覆盖单元配置的正确姿势
3
三、systemctl 高频命令速查
3.1 只看正在运行的服务
3.2 排查”我改的配置到底有没有生效”
4
四、journalctl:systemd 日志的查询入口
4.1 基础查询
4.2 按服务过滤
4.3 按启动会话过滤
4.4 按时间过滤
4.5 按日志级别过滤
4.6 按进程 / 用户过滤
5
五、日志占用与清理
6
六、持久化日志:默认可能没开
7
七、组合姿势:调试服务”启不来”的标准流程
8
八、几条实用经验