在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就能快速看到本次启动的错误日志。运维的效率,就藏在这些日常习惯里。
