在Debian系统上,当服务突然挂掉、系统莫名重启或者某个进程异常退出时,第一反应不应该是重启机器,而是用journalctl命令去翻日志。journalctl是systemd自带的日志查询工具,它把内核日志、服务日志、引导日志全部集中管理,支持按时间、按服务、按优先级过滤,几秒钟就能锁定故障根因。很多运维人员只会用tail去翻/var/log/syslog,效率低还容易遗漏关键信息,journalctl才是Debian 9及以上版本的日志分析核心武器。
一、journalctl到底是什么,为什么比传统日志工具强
传统Linux日志分散在/var/log/目录下的多个文件里,syslog记系统消息,auth.log记认证信息,kern.log记内核事件。排查问题时你得同时打开好几个文件,还要手动grep关键词。journalctl不一样,它把所有日志统一收集到二进制数据库里(默认路径/var/log/journal/),查询时可以按任意维度过滤,而且不需要你知道日志具体存在哪个文件里。对于Debian 10、11、12这些主流版本,journalctl就是默认的日志入口。
二、journalctl的基础用法:先学会这几条命令
最常用的几个场景,直接上命令:
查看本次启动以来的所有日志:
journalctl -b
查看上次启动的日志(排查重启前的问题):
journalctl -b -1
只看错误级别及以上的日志:
journalctl -p err
按时间范围过滤,比如最近30分钟:
journalctl --since "30 minutes ago"
查看某个具体服务的日志,比如nginx挂了:
journalctl -u nginx.service
实时跟踪日志输出,类似tail -f:
journalctl -f
这些命令组合起来,基本覆盖了80%的日常排障场景。
三、实战案例:用journalctl定位五类常见故障
案例1:服务启动失败,报"Failed to start xxx"
Debian上部署了一个自定义服务,执行systemctl start myapp.service后提示失败。这时候直接运行:
journalctl -u myapp.service -b --no-pager
加上--no-pager是为了避免输出被less截断。你会看到完整的启动过程,从服务初始化到哪一步报错、报什么错,一目了然。常见原因包括配置文件路径错误、依赖服务未启动、权限不足等。journalctl会精确告诉你是哪一行配置出了问题。
案例2:系统无征兆重启,查不到原因
机器突然重启,登录后用journalctl -b -1查看上次启动的日志,重点关注shutdown和reboot相关信息:
journalctl -b -1 | grep -i "shutdown\|reboot\|oom\|panic"
如果看到"Out of memory"或者"Kernel panic"字样,说明是内存耗尽或内核崩溃导致的重启。如果看到"Watchdog"相关信息,可能是硬件看门狗触发了重启。journalctl的时间戳精确到微秒级,你可以看到重启前最后几秒发生了什么。
案例3:磁盘空间突然满了,找不到哪个进程在写
先用journalctl按时间过滤,找到磁盘满之前的日志:
journalctl --since "2024-01-15 10:00:00" --until "2024-01-15 10:30:00" | grep -i "disk\|space\|write"
结合du命令定位大文件目录,再用journalctl -u xxx.service确认是哪个服务在疯狂写日志。很多时候是某个应用的debug日志级别开太高,或者日志轮转没配置好,journalctl能帮你快速确认是哪个unit在搞事情。
案例4:网络连接间歇性断开
网络问题最头疼,因为它不像服务崩溃有明确报错。用journalctl过滤网络相关日志:
journalctl -b | grep -i "network\|eth\|link\|dhcp"
重点看NetworkManager或者systemd-networkd的日志,看有没有"link down"、"DHCP timeout"、"carrier lost"这类信息。如果发现每次断网前都有某个网卡驱动报错,那基本可以锁定是驱动兼容性问题或者硬件故障。
案例5:权限被拒绝,服务跑不起来
服务启动报Permission denied,直接查:
journalctl -u myapp.service -b | grep -i "permission\|denied\|selinux\|apparmor"
Debian默认启用AppArmor,很多时候是AppArmor策略拦截了服务的某些操作。journalctl会明确告诉你是哪个文件访问被拒绝、被哪个profile拦截。这时候去/etc/apparmor.d/里调整对应的策略文件就行。
四、journalctl的高级过滤技巧,提升排障效率
光会基础命令还不够,这些进阶用法能让你在海量日志里秒定位:
按PID过滤,某个进程崩了想看它的所有日志:
journalctl _PID=1234
按可执行文件路径过滤:
journalctl /usr/bin/mysqld
查看某个时间段内所有错误日志并显示完整输出:
journalctl --since "2024-01-15 08:00" --until "2024-01-15 09:00" -p err --no-pager
只看内核日志(等同于dmesg但更强大):
journalctl -k
导出日志到文件方便后续分析:
journalctl -u nginx.service --since today > /tmp/nginx_debug.log
查看日志占用的磁盘空间:
journalctl --disk-usage
五、journalctl日志管理:别让日志把磁盘撑爆
journalctl的日志默认是持久化存储的,时间久了会占大量磁盘空间。Debian上可以通过编辑/etc/systemd/journald.conf来控制:
[Journal] SystemMaxUse=500M RuntimeMaxUse=200M MaxFileSec=7day Compress=yes ForwardToSyslog=no
SystemMaxUse限制日志总大小,RuntimeMaxUse限制运行时内存中的日志量,MaxFileSec设置日志保留天数,Compress开启压缩能省不少空间。改完后重启journald服务生效:
systemctl restart systemd-journald
如果是临时机器或者容器环境,可以直接设置Storage=volatile让日志只存内存,重启就清空。
六、journalctl与其他工具的配合使用
journalctl不是万能的,有些场景需要配合其他工具:
和grep/awk配合做文本分析:journalctl输出本身就是结构化文本,管道给awk可以做统计,比如统计某个错误出现的频率:
journalctl -b -p err | awk '{print $5}' | sort | uniq -c | sort -rn
和systemctl status配合:先用systemctl status看服务状态摘要,再用journalctl -u看详细日志,两步走最稳妥。
和logrotate配合:虽然journalctl自带轮转,但如果你同时还在用传统的rsyslog写文件日志,记得配置logrotate避免/var/log下的文件无限增长。
和fail2ban配合:fail2ban可以监控journalctl输出的日志,自动封禁频繁触发错误的IP,适合防暴力破解场景。
七、Debian运维中容易踩的坑
坑1:journalctl -b看不到上次启动的日志。原因是persistent存储没开启,检查/var/log/journal目录是否存在,不存在的话创建它并重启journald:
mkdir -p /var/log/journal systemctl restart systemd-journald
坑2:日志时间显示不对。确认系统时区设置正确,journalctl默认用本地时间,可以加--utc切换到UTC时间查看。
坑3:过滤不到想要的信息。检查日志优先级是否正确,journalctl的优先级从高到低是:emerg(0)、alert(1)、crit(2)、err(3)、warning(4)、notice(5)、info(6)、debug(7)。用-p err只会显示err及以上级别,如果你的问题是warning级别的,需要降低过滤门槛。
坑4:容器里用不了journalctl。Docker容器默认没有systemd或者journald,需要单独安装或者用其他日志方案。
八、总结:把journalctl变成你的排障第一反应
Debian运维的核心能力之一就是快速从日志里找到问题。journalctl提供了比传统工具强得多的查询能力,时间过滤、服务过滤、优先级过滤、PID过滤这些功能组合起来,几乎能应对所有常见故障场景。建议把本文提到的常用命令整理成一个cheatsheet贴在终端旁边,遇到问题第一时间journalctl -b -p err,养成习惯后排障效率会提升一个量级。日志分析不是玄学,是方法论,journalctl就是这个方法论里最趁手的工具。
