Ubuntu系统从15.04版本开始全面采用systemd作为初始化系统,journalctl就是systemd自带的日志查询工具,它取代了传统的/var/log/messages、/var/log/syslog等分散式日志文件。想快速定位系统问题,你必须掌握journalctl的查询与过滤技巧。核心命令其实就几个:按时间过滤用--since和--until,按服务过滤用-u,按优先级过滤用-p,按启动次数过滤用-b,按进程PID过滤用_PID=。把这些组合起来用,90%的运维排障场景都能覆盖。
很多运维人员刚接触Ubuntu时还在用grep去翻/var/log下的文本文件,效率极低。journalctl的优势在于它是二进制日志,支持结构化查询,速度快、功能强。下面我把所有实用技巧按场景分类讲透。
一、journalctl基础认知:日志存储在哪里journalctl读取的日志默认存储在/var/log/journal/目录下(如果是持久化模式)。如果你发现这个目录不存在,说明系统没有开启日志持久化,重启后日志会丢失。开启方法很简单:
sudo mkdir -p /var/log/journal sudo systemd-tmpfiles --create --prefix /var/log/journal sudo systemctl restart systemd-journald
做完这一步,日志就会持久保存了。查看当前日志占用空间可以用:
journalctl --disk-usage
如果磁盘空间紧张,可以限制日志最大占用:
sudo journalctl --vacuum-size=500M
这条命令会把日志压缩到500MB以内。也可以按时间清理,比如只保留最近7天:
sudo journalctl --vacuum-time=7d二、按时间范围查询:最常用的过滤方式
排查问题时,第一步永远是锁定时间窗口。journalctl支持非常灵活的时间表达式。
查询今天的所有日志:
journalctl --since today
查询最近1小时的日志:
journalctl --since "1 hour ago"
查询指定时间段,比如2024年6月1日到6月5日:
journalctl --since "2024-06-01 00:00:00" --until "2024-06-05 23:59:59"
也支持相对时间,比如"昨天":
journalctl --since yesterday --until today
这里有个实用技巧:加上--no-pager可以取消分页,直接输出到终端,方便配合grep或awk做二次处理:
journalctl --since today --no-pager | grep -i error三、按服务单元过滤:精准定位某个程序的日志
这是日常运维中用得最多的功能。比如你想看nginx的日志:
journalctl -u nginx.service
如果服务名不确定,先列出所有正在运行的服务:
systemctl list-units --type=service --state=running
然后找到对应的单元名。注意,有些服务的单元名和包名不一样,比如ssh服务的单元名是ssh.service而不是sshd.service(虽然旧系统用sshd)。
查看某个服务最近50条日志并实时跟踪:
journalctl -u nginx.service -n 50 -f
-n 50表示显示最近50条,-f表示follow模式,类似tail -f的效果。
四、按日志优先级过滤:快速筛选错误和警告systemd定义了8个日志优先级,从高到低是:emerg(0)、alert(1)、crit(2)、err(3)、warning(4)、notice(5)、info(6)、debug(7)。运维中最关心的是err及以上级别。
只看错误及以上级别的日志:
journalctl -p err
看警告及以上(包含err、crit、alert、emerg):
journalctl -p warning
如果你只想看当前启动以来的错误:
journalctl -b -p err
-b参数表示当前启动(boot),不加-b则是所有历史启动记录。
五、按启动次数查询:排查重启相关问题系统每次重启都会生成一个新的日志序列。查看上次重启的日志:
journalctl -b -1
-1表示上一次启动,-2表示上上次,以此类推。查看历史启动列表:
journalctl --list-boots
输出会显示每次启动的时间戳和ID,你可以用ID来指定查看:
journalctl --list-boots | head -5 journalctl -b 3a5f2c1d...
这个功能在排查"系统为什么重启"这类问题时特别有用,因为重启原因通常记录在上次启动的日志里。
六、按进程PID和用户过滤:细粒度追踪如果你知道某个进程的PID,可以直接追踪它的日志:
journalctl _PID=1234
注意PID前面有个下划线_,这是journalctl的特殊语法。如果进程已经退出了,journalctl仍然能查到它的历史日志,前提是日志没有被清理掉。
按用户过滤,比如查看用户www-data产生的所有日志:
journalctl _UID=33
33是www-data用户的UID,你可以用id命令查任意用户的UID。
按内核日志过滤(等同于dmesg):
journalctl -k
或者:
journalctl --dmesg七、输出格式控制:让日志更易读
默认输出格式是文本,但你可以改成JSON格式方便程序解析:
journalctl -u nginx.service -o json-pretty
只输出日志消息体,不要时间戳和其他元数据:
journalctl -u nginx.service -o cat
以短格式输出(去掉时间和主机名,只保留优先级和消息):
journalctl -u nginx.service -o short
导出为JSON格式到文件做后续分析:
journalctl --since today -o json > /tmp/today_logs.json
如果你需要在脚本中使用,推荐用--output=json配合jq工具做结构化提取。
八、组合过滤:实战中的高阶用法实际排障时,单一过滤条件往往不够,需要组合使用。比如查看今天nginx服务产生的所有错误日志:
journalctl -u nginx.service --since today -p err
查看上次重启以来sshd服务的所有日志:
journalctl -u sshd.service -b -1
查看最近2小时内优先级为warning以上且包含特定关键字的日志:
journalctl --since "2 hours ago" -p warning --no-pager | grep -i "timeout"
查看某个时间段内某个PID的日志:
journalctl _PID=5678 --since "2024-06-01" --until "2024-06-02"
还有一个容易被忽略的参数--grep,它可以在日志消息内容中做正则匹配:
journalctl --since today --grep "connection refused"九、实时监控与日志轮转注意事项
实时监控日志用-f参数,这个和tail -f一样好用:
journalctl -f
但要注意,journalctl -f默认显示所有日志,信息量可能很大。建议配合服务名或优先级使用:
journalctl -f -u docker.service -p warning
关于日志轮转,journald默认会自动管理日志大小和保留时间。如果你需要更精细的控制,可以编辑/etc/systemd/journald.conf:
[Journal] SystemMaxUse=1G RuntimeMaxUse=500M MaxRetentionSec=1month ForwardToSyslog=no
改完后重启服务生效:
sudo systemctl restart systemd-journald
SystemMaxUse是持久化日志最大占用,RuntimeMaxUse是运行时(/run下)的最大占用,MaxRetentionSec是最长保留时间。
十、常见问题与避坑指南第一个坑:很多人发现journalctl查不到日志,先确认systemd-journald服务是否正常运行:
systemctl status systemd-journald
第二个坑:容器环境中(Docker),默认日志驱动可能是json-file而不是journald,所以容器内用journalctl可能查不到东西。需要在启动容器时指定--log-driver=journald。
第三个坑:如果你把日志导出到syslog或其他地方,journalctl就只保留本地部分。检查配置:
cat /etc/systemd/journald.conf | grep -i forward
第四个坑:时间过滤时注意时区问题。journalctl默认使用系统时区,如果你的服务器是UTC时区但你习惯用北京时间,计算时间窗口时要注意换算。
最后补充一个冷门但有用的技巧:验证日志文件完整性,防止日志被篡改:
journalctl --verify
这条命令会检查所有journal文件的哈希值,确保日志没有被非法修改。在安全审计场景下非常实用。
总结一下,journalctl的核心就是"时间+服务+优先级+启动次数+进程"这五个维度的组合过滤。掌握这些,Ubuntu系统的日志排查效率至少提升5倍以上。建议把常用命令写成alias放到.bashrc里,日常运维会省很多时间。
