在Debian系统上,绝大多数服务都由systemd管理,服务崩溃后的现场信息会被systemd-journald统一收集到journal日志里。journalctl就是读取这些日志的官方工具。很多人遇到服务异常退出时第一反应是去翻应用自己的日志文件,结果发现关键信息早就被journal记录下来了。这篇文章围绕服务崩溃排查这个场景,把journalctl的常用手法整理一遍,帮你快速定位崩溃原因。

一、按服务单元过滤日志,查看崩溃现场
排查服务崩溃的第一步,是把目标服务的日志单独拉出来看,而不是在几千行系统日志里大海捞针。journalctl提供了-u参数,可以按systemd单元名称过滤,比如要查看nginx服务的日志:
journalctl -u nginx.service
如果崩溃发生在最近,加上-e可以直接跳到日志末尾,避免手动翻页;加上-f则类似tail -f,适合在复现崩溃时实时观察输出:
# 跳到最后100行,从服务日志末尾开始看 journalctl -u nginx.service -e -n 100 # 实时跟踪服务日志 journalctl -u nginx.service -f
还有一个非常实用的参数是-b,它表示只看本次开机以来的日志。如果服务是在系统重启后才出问题,加上这个参数能过滤掉上一次运行周期的大量历史记录,让输出更干净。排查崩溃时推荐把这几个参数组合起来用,例如journalctl -u mysql.service -b -e,一眼就能看到本次开机后MySQL最后的日志。
二、从systemd视角定位崩溃与自动重启痕迹
服务崩溃后,systemd本身也会在日志里留下痕迹,这部分信息经常被忽略,但其实非常有价值。用-u查看服务单元状态相关的日志时,你会看到类似“Scheduled restart job”或“Main process exited, code=killed, status=11”这样的记录。其中code=后面的值能直接告诉你退出的方式:
code=dumped:进程发生了段错误(core dump),多半是程序bug或依赖库问题code=killed, status=9:进程被SIGKILL杀掉了,最常见原因是内核OOM killer动手了code=exited, status=1:进程自己退出并返回了非零状态码,通常是启动阶段配置错误
判断OOM有个快捷办法,直接查内核日志里有没有oom-kill的记录:
# 查看内核中是否有OOM记录 journalctl -k | grep -i "out of memory" # 或者直接看内核错误级别日志 journalctl -k -p err
另外,如果怀疑服务一直在反复崩溃又被拉起来,可以配合systemctl status确认。status输出里的重启次数和触发阈值(StartLimitBurst)能说明问题。当服务因为崩溃太频繁被systemd判定进入failed状态时,日志里会有“Start request repeated too quickly”的记录,这时要解决的是崩溃本身,而不是简单地systemctl restart了事。
三、查看历史日志与时间范围过滤
排查崩溃时经常需要回溯:服务昨天半夜挂了,今天才发现。这时候要能查到历史日志,前提是journal做了持久化存储。Debian默认情况下journal数据存放在/run/log/journal,重启后就没了。想让日志落盘,需要创建/var/log/journal目录并重启服务:
mkdir -p /var/log/journal systemd-tmpfiles --create --prefix /var/log/journal systemctl restart systemd-journald
持久化之后,可以用--list-boots列出所有开机记录,再用负数偏移查上一次启动周期的日志,比如-b -1表示上一次开机。如果崩溃发生在重启之前,这是唯一能看到现场的方式:
# 列出所有启动记录 journalctl --list-boots # 查看上一次开机期间的nginx日志 journalctl -u nginx.service -b -1
时间过滤用--since和--until,写法支持多种格式,比如“昨天”“2024-03-01 02:00”等。这里有个常见的坑:如果写的时间格式不被识别,journalctl可能不报错而是输出空结果,让人误以为没有日志。建议用标准的日期加时间格式,并用引号包起来:
# 查看某个时间段内的服务错误日志 journalctl -u myapp.service --since "2024-03-01 00:00" --until "2024-03-01 06:00" # 只看错误级别及更严重的日志 journalctl -u myapp.service -p err..alert
-p参数按优先级过滤日志,可选值从emerg到debug。排查崩溃时用-p err通常就够了,能过滤掉大量无关的info级输出,直接聚焦报错信息。如果还想看崩溃瞬间的core dump详情,可以确认systemd-coredump是否启用,然后用coredumpctl list列出崩溃记录,用coredumpctl info <PID>查看具体堆栈。
四、几个提高排查效率的实用技巧
除了上面这些主线命令,再补充几个日常很省事的用法。第一个是--grep参数,可以直接在journal里按正则搜索,比先输出再grep管道要快,例如journalctl --grep "segfault"能快速找出所有段错误记录。注意这个参数依赖journal的索引功能,老版本systemd可能不支持,Debian 11之后都没问题。
第二个技巧是输出格式控制。默认日志每条占好几行,带时间戳和主机名,排查大量日志时可以用-o cat只输出正文部分,配合-r倒序显示,先看最新的错误:
# 只显示消息正文,倒序输出 journalctl -u myapp.service -o cat -r -n 200
最后提醒一点权限问题。普通用户执行journalctl默认只能看到自己的日志,查看系统服务日志需要把用户加入systemd-journal组,或者直接用root执行。有些人在普通用户下查日志发现输出是空的,就以为是日志丢了,其实只是权限不够。把这些命令组合用熟之后,Debian上绝大多数服务崩溃问题都能在journal里找到直接线索,比盲目猜测重启原因高效得多。
journalctlDebian服务崩溃日志修改时间:2026-09-09 08:30:46