在Ubuntu系统运维中,遇到服务崩溃、启动失败、内核报错等异常时,journalctl就是你最直接的排查工具。它是systemd自带的日志管理命令,能按时间、服务单元、优先级等维度快速过滤日志,帮你在几分钟内定位问题根因。很多运维新手习惯去翻/var/log/下的零散日志文件,效率低且容易遗漏关键信息,而journalctl把所有日志统一收集、索引、管理,一条命令就能搞定大部分排查场景。

journalctl是什么,为什么Ubuntu运维必须掌握它

journalctl是systemd-journald服务的查询前端工具。Ubuntu从15.04开始全面采用systemd作为初始化系统,所有服务启动日志、内核消息、用户会话记录都被systemd-journald统一收集存储。日志数据默认保存在/var/log/journal/目录(如果启用了持久化存储),或者以/run/log/journal/下的内存形式存在(重启丢失)。相比传统的syslog,journalctl支持结构化日志、二进制索引、精确时间戳,查询速度快、过滤能力强,是现代Linux运维的基本功。

journalctl的基础使用:先看懂日志在哪里

在排查之前,你需要确认日志是否持久化存储。默认情况下,很多Ubuntu发行版的/var/log/journal/目录不存在,日志只在内存中。执行以下命令开启持久化:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

确认完成后,直接输入journalctl不加任何参数,会打开一个类似less的分页界面,显示所有日志从最早到最新。按q退出,按空格翻页,方向键上下滚动。这个默认视图信息太多,实际排查时我们几乎不会这样用,而是加各种过滤参数。

按时间范围排查:最常用的过滤方式

系统出问题时,你通常知道大概出问题的时间段。journalctl支持非常灵活的时间过滤:

journalctl --since "2024-01-15 10:00:00" --until "2024-01-15 12:00:00"
journalctl --since "1 hour ago"
journalctl --since "today"
journalctl --since "yesterday" --until "today"

--since和--until可以组合使用,支持"20 min ago"、"yesterday"、"this week"等自然语言表达。如果你只想看最近一次启动后的日志(排除历史启动记录),用-b参数:

journalctl -b

如果系统经常重启,想看上一次启动的日志:

journalctl -b -1

列出所有启动记录:

journalctl --list-boots

按服务单元排查:精准定位哪个服务出了问题

当你怀疑某个服务异常时,直接指定服务名过滤。比如排查nginx、ssh、docker的问题:

journalctl -u nginx.service
journalctl -u ssh.service
journalctl -u docker.service

如果服务名不确定,先列出所有正在运行的服务:

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

也可以同时指定多个服务:

journalctl -u nginx.service -u mysql.service

想看某个服务最近10分钟的日志:

journalctl -u nginx.service --since "10 min ago"

按优先级排查:快速筛选错误和警告

日志量大时,你只想看错误级别以上的信息。journalctl的优先级从高到低为:emerg(0)、alert(1)、crit(2)、err(3)、warning(4)、notice(5)、info(6)、debug(7)。常用过滤:

journalctl -p err      # 只看错误及以上
journalctl -p warning  # 错误+警告
journalctl -p crit     # 严重+错误+警告

也可以用数字:

journalctl -p 3  # 等同于 -p err

按内核消息排查:硬件和驱动问题专用

如果怀疑是内核层面的问题(比如网卡掉线、磁盘IO错误、OOM killer触发),直接看内核日志:

journalctl -k
journalctl -k --since "1 hour ago"

-k参数等同于--dmesg,显示内核环形缓冲区的消息。OOM killer触发时,你会在这里看到"Out of memory: Killed process"之类的关键信息。

实时监控日志:像tail -f一样跟踪

排查正在发生的问题时,实时跟踪日志非常有用:

journalctl -f
journalctl -f -u nginx.service

-f参数让日志实时滚动输出,新日志出现时立即显示。配合-u指定服务,可以只跟踪特定服务的实时状态。按Ctrl+C退出。

输出格式控制:让日志更易读

默认的journalctl输出包含时间戳、主机名、进程信息等,有时你需要更简洁或者更详细的格式:

journalctl -o short-full    # 显示完整日志内容,不截断
journalctl -o json-pretty   # JSON格式,方便脚本解析
journalctl -o cat           # 只显示日志消息,不显示元数据
journalctl -o verbose       # 显示所有可用字段

如果日志内容被截断显示(显示"..."),用--no-pager跳过分页器并配合-o short-full:

journalctl --no-pager -o short-full

实战场景一:服务启动失败排查

假设你的MySQL服务启动失败,执行systemctl status mysql.service看到failed状态。第一步:

journalctl -u mysql.service -b --no-pager

查看本次启动的完整日志。通常你会看到类似"Can't start server: Bind on TCP port: Address already in use"或者"InnoDB: Unable to lock"之类的错误。找到具体报错行后,根据错误信息去处理端口占用、权限、配置文件等问题。如果日志太长,加上-n限制行数:

journalctl -u mysql.service -b -n 50 --no-pager

实战场景二:系统突然重启排查

系统意外重启,想知道重启前发生了什么。先看启动历史:

journalctl --list-boots

找到异常重启那次的启动ID,然后查看:

journalctl --list-boots | grep "2024-01-15"
journalctl -b <启动ID>

如果怀疑是硬件问题,加上-k看内核日志:

journalctl -b <启动ID> -k

常见原因包括:内存不足触发OOM、硬件过热、电源故障、内核panic等。内核panic的日志中会有"Kernel panic - not syncing"字样,这是致命错误,通常指向硬件或驱动问题。

实战场景三:磁盘空间满导致服务异常

有时候服务报错不是服务本身的问题,而是磁盘满了。先看系统日志中是否有"No space left on device":

journalctl --since "2 hours ago" | grep -i "no space"
journalctl -p err --since "2 hours ago" | grep -i "space"

确认后清理日志或扩容磁盘。另外,journalctl本身也会占磁盘空间,如果日志太大可以清理:

journalctl --vacuum-time=7d    # 保留7天日志
journalctl --vacuum-size=500M  # 限制日志总大小为500M
journalctl --verify            # 检查日志完整性

实战场景四:SSH登录失败排查

用户反馈无法SSH登录,先看sshd服务日志:

journalctl -u ssh.service --since "1 hour ago" --no-pager

常见原因包括:密码错误次数超限(会看到"Failed password")、密钥认证失败、sshd配置被修改、防火墙规则变更等。如果是暴力破解攻击,你会看到大量"Failed password for root"的记录,这时需要考虑禁用root密码登录或配置fail2ban。

journalctl的高级技巧和注意事项

几个实用的高级用法值得记住。第一,用--disk-usage查看日志占用空间:

journalctl --disk-usage

第二,如果日志文件损坏,用--verify检查:

journalctl --verify

第三,想把日志导出给别人分析,用重定向:

journalctl -u nginx.service --since today > nginx_debug.log

第四,journalctl的日志存储位置和配置在/etc/systemd/journald.conf,可以调整SystemMaxUse、MaxRetentionSec等参数控制日志保留策略。注意:journalctl只能查看systemd管理的日志,对于应用自己写到/var/log/下的独立日志文件(如apache的access.log),还是需要传统方式查看。

常见误区和避坑指南

很多人犯的错误是不加任何过滤参数直接跑journalctl,面对几万行日志无从下手。正确的做法是先缩小范围:确定时间段、确定服务名、确定优先级,三个维度至少锁定两个。另外,journalctl默认显示的是本地日志,如果你在排查远程服务器,需要通过SSH登录后执行。还有一点,journalctl查看的是systemd-journald收集的日志,如果某个服务用的是传统syslog方式写日志且没有被systemd捕获,你可能看不到,这时候需要检查/etc/rsyslog.conf或服务自身的日志配置。

总结:把journalctl变成你的排查肌肉记忆

Ubuntu运维中,journalctl不是可选工具,而是必选工具。它把过去需要翻多个日志文件、用grep反复过滤的工作,浓缩成一条命令完成。掌握时间过滤(-b、--since、--until)、服务过滤(-u)、优先级过滤(-p)、内核过滤(-k)、实时跟踪(-f)这几个核心参数,就能覆盖90%以上的日常排查场景。建议把常用命令写成alias放在~/.bashrc里,比如alias jl='journalctl -p err -b --no-pager',遇到问题直接敲jl就能快速看到本次启动的错误日志。运维的效率,就藏在这些日常习惯里。