排查Linux服务器问题的时候,我十有八九会先敲一条命令:journalctl。它是systemd体系下的日志查询工具,几乎所有跑新发行版的机器都会带它。和传统“一个/var/log/messages写到老”的方式不同,journald会把内核、服务、用户程序产生的日志统一收进一套带索引的二进制日志库里,再用journalctl按服务、时间、级别、关键字过滤。这篇文章不打算列手册里的所有参数,而是把一个运维老兵在日常排障、容量治理、日志持久化里真正用得到的部分,掰开揉碎讲一遍。无论你是刚接触Linux的运维新人,还是已经用过一阵 journalctl -f 的老手,应该都能找到点有用的东西。
1. 为什么排查问题我总是先打开journalctl
1.1 一个真实的“半夜故障”场景
前阵子半夜接到告警,线上Nginx大面积502。我第一反应不是去看业务日志,而是先登录服务器跑了两条命令:
bash复制systemctl status nginx
journalctl -u nginx -n 50 --since "10 min ago"
第一条命令看服务是不是活着,第二条命令直接看最近10分钟Nginx服务的完整输出。结果没翻几页就发现worker进程在反复崩溃,紧跟着一条 connection limit exceeded 的报错,问题瞬间定位到了连接数配置上。整个过程不到五分钟。
这就是我日常最典型的journalctl用法:刚出事的时候,别急着翻各种文件,先用时间窗口把相关服务最近几分钟的日志拖出来看一眼。journald默认会收集服务进程的stdout和stderr,所以很多平时“从不写日志”的服务,在journal里也能看到完整输出。这个特性,老syslog体系下想都不敢想。
1.2 journald和旧日志体系到底差在哪
Linux传统日志体系是“文件+追加”模式:内核往/var/log/kern.log写,用户服务往/var/log/messages或/var/log/syslog写,应用各自再往自己的文件写。查询基本靠grep,想按时间过滤要结合sed/awk,想看某服务今天的日志更是要在一堆文本里翻来翻去。
journald改变了这个格局。它由systemd启动,核心功能就一个:统一收日志。内核消息、系统服务输出、syslog转发、进程通过sd_journal接口主动提交的日志,全部汇入一张“网”。journalctl就是这个网的查询入口。
| 对比项 | 传统syslog/文件日志 | journald + journalctl |
|---|---|---|
| 数据格式 | 纯文本,靠约定解析 | 二进制加结构化字段,带索引 |
| 查询方式 | grep/awk硬筛 | 按服务、时间、级别、PID等字段过滤 |
| 收集范围 | 需要单独配置syslog规则 | 服务stdout/stderr默认自动收集 |
| 磁盘占用 | 固定文件,满了要自己轮转 | 默认限额,超过后自动清理(需配置) |
| 时间定位 | 需要额外写脚本 | --since/--until直接定位,天然支持启动序号 |
说白了,journald不是要取代所有文件日志,而是把“系统层面到底发生了什么”这件事统一管起来。应用自己的业务日志当然还是打文件、接日志平台,但系统级事件查journal就对了。
1.3 第一次使用前要搞清楚的基础概念
用journalctl之前,脑子里要有三个基本概念:
第一条,journald是后台守护进程,journalctl只是它的查询客户端。journald负责收集、存储、轮转,journalctl负责把数据用人类可读的方式展示出来。
第二条,日志存在/run/log/journal(内存临时目录)或/var/log/journal(磁盘持久化目录)。如果系统里没有/var/log/journal目录,默认日志只放内存,一重启就全没了。这是个极度常见的坑,后面我会专门讲怎么改。
第三条,普通用户只能查看自己用户会话相关的日志,想看系统级服务日志,要么是root,要么把自己加进systemd-journal组。公司内网机器我一般建议运维账号直接加组,不然每次sudo非常烦。
注意:
journalctl命令本身不产生日志,它只是读取systemd-journald写好的二进制日志库。很多人误以为它是“实时抓取命令”,其实它是“实时查询命令”。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. journalctl高频参数实战,按使用频率排序
2.1 查服务日志:-u 就是最核心的用法
使用频率最高的一定是 -u,后面跟服务名,查看指定systemd服务的日志:
bash复制# 查看Nginx服务的全部日志
journalctl -u nginx.service
# 服务名不带.service也能识别
journalctl -u nginx
# 同时查看多个服务的日志
journalctl -u nginx -u mysql.service
这里有个经验:服务名最好写完整,
