news 2026/9/9 7:43:53

Ubuntu日志管理实战:journald、rsyslog、logrotate三驾马车详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu日志管理实战:journald、rsyslog、logrotate三驾马车详解

废话不多说,第7课咱们聊一个平时感知不强、但出问题时能救命的主题——日志管理。很多新手拿到一台 Ubuntu 服务器之后,第一反应就是到处翻/var/log目录,看到一堆.log文件就以为日志管理不过如此。真到排查故障的时候才发现,日志乱成一团、文件大到打不开、重启之后历史日志全没了,甚至磁盘被日志写满导致服务崩溃,这些问题全部指向同一个答案:你还没有把 Ubuntu 的日志体系真正摸透。

这一篇我打算把 Ubuntu 日志管理里的三驾马车一次讲清楚:rsyslog、journald、logrotate。不看官方文档那种照本宣科式的堆砌,只讲实际运维中怎么用、为什么这么用,以及哪些坑我用几百个小时的踩坑经历帮你提前填了。不管你是刚接触 Linux 的小白,还是已经部署过几个项目的进阶玩家,这篇都可以当成一份随手能查的日志管理实操手册。

1. 先把日志体系捋清楚:rsyslog、journald、logrotate 到底各管什么

很多人一上来就直接查命令、背参数,结果越学越乱,因为脑子里面没有一个整体架构图。Ubuntu 的日志体系不是某一款软件单打独斗,而是三个组件各管一段、互相配合,少了一个都会出问题。

先说 journald。它是 systemd 自带的日志守护进程,从 Ubuntu 15.04 之后就跟 systemd 深度绑定在一起。它的最大特点是“中央车站”,系统里所有服务的标准输出、内核日志、启动信息,只要交给 systemd 管理的,都会自动汇入 journald。也就是说不管这个服务的日志原本想往哪里写,journald 都能拦一份下来,用二进制格式存在内存或磁盘上,你用journalctl命令就能统一查询。这个设计非常方便,但代价是它是二进制格式,普通cattail看不出来内容,必须借助专用工具。

再说 rsyslog。它在 Ubuntu 里是老牌选手了,负责的是“分流与归档”。journald 把日志收进来,rsyslog 则按你定义的规则把日志写到具体的文本文件里,或者转发到远程日志服务器。很多老运维习惯了直接看/var/log/syslog/var/log/auth.log,这些其实都是 rsyslog 根据配置文件生成的文本日志。rsyslog 的强项是灵活的路由规则和成熟的远程转发机制,在集中式日志、安全审计场景里非常重要。

最后说 logrotate。它是一个日志轮转工具,核心解决一件事:避免单个日志文件无限膨胀。日志持续增长是必然的,如果不处理,一个文件的体积能涨到上百 GB,磁盘被打满只是时间问题。logrotate 通过定期切换、压缩、删除历史日志来控制磁盘占用,是日志管理的最后一道防线。

这三个组件的关系可以类比成一个完整的日志处理流水线:journald 负责源头采集,rsyslog 负责按需派发,logrotate 负责定期清理归档。三者配合好了,系统的日志才既完整、又干净,还不会吃光磁盘。

1.1 三个组件如何分工协作,一张说明理清职责边界

我在教学的时候喜欢让学生先记住一句话:journald 管收集,rsyslog 管网关,logrotate 管轮转。可以把这个结构想象成一个快递分拣中心——各业务线产生的包裹(日志)先全部送到总站(journald),总站扫描分类后,有的按目的地送上长途车,有的放到自提柜(rsyslog 分流到文件/远程);但快递柜再大也有容量上限,所以仓管员(logrotate)定期清理旧包裹,腾出空间装新货。

实际干活的时候,你差不多会按照下面的链路来理解:

  • 服务进程带着自己的日志请求直接走 systemd 的标准输出,journald 自动接住。
  • 同时,/dev/log这个 socket 上仍然有传统 syslog 协议的日志在流动,rsyslog 会从这边接住,再根据 facility 和 priority 规则写入文本文件。
  • 最后系统每天或每周通过 cron 触发一次 logrotate,逐个日志文件做“改名-重建/压缩/清理”的动作。

我之前遇到一个挺典型的误解:有人以为关掉了 rsyslog 服务,系统日志就不写了。其实 journald 照样在收集,只是/var/log/syslog这些文本文件不再更新了。同理,如果 journald 因为磁盘满了罢工,journalctl查不出东西,但 rsyslog 可能还是正常往文本文件写。明白这一点,你排障的时候就不会被“日志突然没了”这种假象带偏。

1.2 配置文件先认门,动手之前心里要有数

Ubuntu 上每个组件都有对应的核心配置目录,动手之前先把门认清楚,比记住一长串命令更关键。我先替你整理一份“配置文件地图”,后面所有操作都围绕这几张表展开:

组件配置文件作用说明
journald/etc/systemd/journald.conf控制 journald 存储方式、日志大小上限、转储策略
rsyslog/etc/rsyslog.conf/etc/rsyslog.d/定义日志接收、过滤、写入、转发规则
logrotate/etc/logrotate.conf/etc/logrotate.d/控制轮转周期、保留轮数、压缩开关
系统日志文件/var/log/rsyslog 默认输出目录,部分服务日志也在这里
systemd journal 持久化/var/log/journal/journald 持久化存储目录,默认可能不存在

我最常提醒新手的一句话是:改 rsyslog 和 journald 的配置之后,记得重启对应服务。这听起来像废话,但真的有人改完配置文件坐等生效,结果排了一下午的错,最后才发现服务没重载。rsyslog 重载用sudo systemctl restart rsyslog,journald 用sudo systemctl restart systemd-journald,两个命令各管一摊,别搞混。

2. journald:系统日志的“中央车站”,先把它玩明白

journald 是现在 Ubuntu 日志体系里最先触达日志的组件,所有被 systemd 托管的服务,标准输出和标准错误都会自动进入 journald。这意味着你不用每个应用单独配置日志路径,直接用journalctl就能把多个服务的日志放在一起看,排查问题时特别省事。

一句话总结 journald 的核心优势:统一入口、结构化存储、按服务过滤。它不依赖日志文件路径,也不依赖服务自己有没有写文件的能力,只要你系统里进程是通过 systemd 拉起来的,日志就“逃”不掉。这也是为什么现在很多新装的服务,比如 Nginx、MySQL、Docker,你会发现journalctl -u能查到它们的输出,尽管它们根本没往 syslog 写东西。

2.1 journalctl 的常用姿势,直接拿来就用

掌握 journalctl,基本等于掌握了 Ubuntu 排障的第一把钥匙。我一个一个讲,每个命令后面配一个实际场景,你能直接对着用。

先看最基础的全量日志:

journalctl

不加任何参数,jounald 会从最早可用的记录开始输出所有日志。如果系统运行时间长,这个命令的输出量大到吓人,一般我只在确认日志总量不太大时才会用。更常用的做法是加-u指定服务:

journalctl -u nginx.service

这条命令只看 nginx 服务的日志。说实话,这才是日常最常用的姿势,服务报错了、起不来了、端口被占了,第一件事就是看这个服务的日志。如果还想看最近 30 分钟内的日志:

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

--since--until是特别好用的时间过滤参数,格式也很灵活,可以是 “30 min ago”“2025-01-01 10:00:00”“yesterday” 这类人类能读懂的写法。我排查问题的时候习惯先拉最近十分钟的日志,再根据线索往前推时间窗口,比直接全量输出高效得多。

内核日志是另一类高频需求。当遇到网络不通、硬件识别异常、驱动加载失败等问题时,直接看内核日志比翻dmesg更好用,因为 dmesg 显示的是内核环形缓冲区里的内容,而journalctl -k查的是 journald 记录的内核日志,信息量和筛选能力都更强:

journalctl -k

查某个具体时间点附近的系统整体状态,可以组合使用:

journalctl --since "2025-01-01 09:00" --until "2025-01-01 09:30"

日志量大的时候,我会直接进交互模式看 tail,这也是最容易上手的方式,就把它当成升级版的 tailf:

journalctl -f

最后是两个需要特别留意的参数。-p可以按日志优先级过滤,比如只看错误和更严重的:

journalctl -p err

优先级从高到低分别是 emerg、alert、crit、err、warning、notice、info、debug。-o json-pretty可以把日志按 JSON 格式化输出,方便写脚本做二次分析:

journalctl -u nginx.service --since "10 min ago" -o json-pretty

我自己的排查习惯是:先-p err看有没有硬错误,再-u锁定服务,最后用--since收窄时间范围,三步基本能定位 70% 的问题。

2.2 日志要不要持久化,这是一个决策题

journald 默认情况下把日志存在内存文件系统/run/log/journal里。重启服务器,这些日志就会清空。这一点在设计上是有意为之的,避免日志写入拖慢磁盘、减少闪存设备的写入损耗;但对生产环境来说,“重启之后日志全没了”是灾难级的设定,因为很多故障恰恰发生在重启的瞬间。

开启持久化其实只需要一个动作:

sudo mkdir -p /var/log/journal

然后重启 journald 服务:

sudo systemctl restart systemd-journald

为什么创建目录就够了?因为 journald 的存储逻辑很简单:只要/var/log/journal目录存在,它就把日志往磁盘写,否则就退回内存。这个设计确实有点“隐藏彩蛋”的味道,官方文档里写得很含蓄,很多人根本不知道。我遇到过一台跑了几年的服务器,有一天journalctl突然查不到三个月前的日志,排查了半天,原因是/var/log/journal被人误删了,journald 无声无息地退回了内存模式。

注意,创建目录之后最好顺便检查一下属主:

ls -ld /var/log/journal

如果是 root root,journald 仍然能写,因为它是 root 权限运行的;但为了规范,可以执行:

sudo chown root:systemd-journal /var/log/journal

关于持久化的判断标准,我给一个参考:桌面开发机可以不持久化,因为日志量小、丢失也无所谓;但服务器、部署了业务应用、需要审计追踪的机器,必须持久化。### 2.3 磁盘占用控制:别让日志反噬了业务

journald 持久化之后,日志文件会不断增加,控制磁盘占用就成了新任务。journald 的容量控制参数全在/etc/systemd/journald.conf里,改完同样要重启 systemd-journald 才能生效。

我最关心的三个参数是SystemMaxUseSystemKeepFreeRuntimeMaxUseSystemMaxUse表示 journald 最大能用多少磁盘空间,默认是总磁盘的 10%;SystemKeepFree表示 journald 至少要为其他用途保留多少空间,默认 15%;RuntimeMaxUse表示日志存在内存时最大占用,默认是内存大小的 10%。

如果磁盘空间紧张,我会直接把 SystemMaxUse 压到一个固定值,比如 200M。修改配置文件:

[Journal] SystemMaxUse=200M SystemKeepFree=50M

有人认为日志保留越多越好,我觉得这其实是个误区。日志的意义在于排查问题,超过三个月的老日志基本没人看,却白白占着磁盘。与其无限堆存量,不如配合下面的清理动作。

手动清理的命令也很直白。查看日志磁盘占用:

journalctl --disk-usage

把日志总量压缩到 100M 以内:

journalctl --vacuum-size=100M

按时间清理,只保留最近 7 天:

journalctl --vacuum-time=7d

这几个命令执行完会立刻释放磁盘空间,适合磁盘告警时当救火队员。我个人推荐的做法是:持久化打开,同时把SystemMaxUse设成 500M 左右,然后每月手动跑一次--vacuum-time=30d,这样既不担心磁盘被撑爆,也能确保有近一个月的完整日志可查。

3. rsyslog:把日志按规矩分流、归档、送出去

journald 负责收集,但很多时候我们不能只满足于收集。你想让认证日志单独存成一个文件、想把自己的应用日志从一堆杂音里隔离出来、想同时把日志转发到远程服务器,这些需求都是 rsyslog 的主场。

rsyslog 最传统的规则格式是 “facility.priority action”,一句话就能表达“什么来源、什么级别的日志,送到哪里去”。看着像天书,拆开就很简单。

3.1 facility.priority 这套规则到底怎么读

facility 指的是日志的来源类型,常见的有 auth(认证)、authpriv(私有认证)、cron(计划任务)、daemon(守护进程)、kern(内核)、lpr(打印)、mail(邮件)、user(用户进程)等。priority 是日志的紧急程度,从高到低排序是 emerg、alert、crit、err、warning、notice、info、debug。

规则里还有几个特殊符号要注意。*表示所有 facility 或所有 priority;=表示精确匹配某一优先级;!表示取反;.表示“该级别以及更高优先级”,.*表示该级别及以下的所有日志。这套表达方式初看容易绕,实际用熟了非常灵活。

拿 Ubuntu 默认配置里一条经典规则举例:

*.*;auth,authpriv.none -/var/log/syslog

意思是:所有来源、所有级别的日志,除了 auth 和 authpriv 这两种之外,其余都写到 /var/log/syslog。这里的-前缀表示异步写入,也就是先把日志放内存缓冲,再批量落盘,换取更高的写入性能;代价是如果突然断电,缓冲里还没来得及写盘的日志会丢掉。

我之前给一家公司做日志规范时,看过他们把 auth 日志忘掉的坑。安全审计需要查登录记录,结果/var/log/auth.log一张表拉到半年以前,记录确实都在,可中间偏偏空了一周,原因是某次误操作把authpriv.none写成了*.*的前置条件,认证日志被静默丢弃。从那以后我养成了一个习惯:改完任何 rsyslog 规则,先手动触发一条认证尝试,再去 auth.log 里确认有没有落盘。日志系统本身如果坏了,那比业务出问题还可怕,因为你连怎么挂的都不知道。

3.2 自定义分流规则:让日志去它该去的地方

光看不练没意思。我给你一个非常常见的定制需求:把 OpenSSH 的认证日志单独分离出来。

OpenSSH 的日志 facility 是 auth,authpriv 由它自己掌握。Linux 的 sshd 默认使用 authpriv,所以只要在/etc/rsyslog.d/下新建一个文件,比如50-ssh.conf,写入:

authpriv.* /var/log/ssh.log

保存之后重启 rsyslog:

sudo systemctl restart rsyslog

验证就简单了,故意输错一次 SSH 密码,然后检查:

sudo tail -f /var/log/ssh.log

你会看到 sshd 的认证失败记录。如果日志没出现,优先检查两个方向:一是 sshd 是否走的是 authpriv 而不是 auth,二是规则文件是否被其他规则提前匹配截胡。rsyslog 规则是按文件顺序从上到下执行的,默认文件里 authpriv 有一堆历史规则,你如果把自己的规则放在 20- 开头的文件里,很可能被前面的命名规则先行处理了,所以我一般建议自定义规则文件名用 50- 或更高数字开头,排在默认规则后面执行。

rsyslog 还支持在配置里用模板定义更精细的日志格式,比如给应用日志加时间戳。这个属于进阶玩法,要用到 RainerScript 语法,感兴趣的人可以再往深了挖。日常分流需求,上面的规则已经能解决九成问题。

3.3 远程日志转发:把日志送到统一的日志中心

单机日志管理只有一半价值,真正规模化之后,多台服务器的日志最好能集中到一个地方统一查询。rsyslog 原生支持 UDP 和 TCP 转发,配置也简单,先看发送端。

假设我要把本机所有日志转发到日志服务器 192.168.1.100,接收端口用 UDP 514:

*.* @192.168.1.100:514

一个 @ 是 UDP,两个 @@ 是 TCP:

*.* @@192.168.1.100:10514

接收端服务器上,rsyslog 需要开启 imudp 或 imtcp 模块,并监听对应端口。编辑/etc/rsyslog.conf,把这两行去掉注释:

module(load="imudp") input(type="imudp" port="514") module(load="imtcp") input(type="imtcp" port="10514")

重启接收端和发送端的 rsyslog,日志就会开始流动。注意一点:UDP 丢包不重传,对日志完整性要求高的话一定用 TCP。另外,默认的 syslog 端口 514 需要 root 权限监听,某些 Ubuntu 版本还要配置防火墙放行端口,否则转发会失败但没有任何报错,非常容易让人抓狂。

我在多个场景里用过 rsyslog 远程转发,最典型的两个:一是安全审计要求登录日志集中留存,二是多台业务服务器日志统一汇总后用脚本分析。只要遵守“发送端配目标地址、接收端开监听模块”这个思路,基本不会跑偏。有人问 UDP 和 TCP 延迟差距会不会影响实时性,我自己的体验是不用纠结,日志对毫秒级延迟并不敏感,重点是别丢。

4. logrotate:日志文件过大、磁盘被打爆的终极防线

journald 管存储上限,rsyslog 管日志分发,但还有一类日志是它们都不太管的:应用自己写出来的文本日志。像 Nginx 的 access.log、MySQL 的 error.log、PostgreSQL 的日志,这些文件如果应用自己不清理,就会无限增长。logrotate 就是专门负责“给日志文件瘦身”的工具,它既管 rsyslog 体统生成的日志,也管应用自己写的日志,是系统日志管理的兜底方案。

很多人第一次听到“rotate”觉得很抽象,其实它做的事情特别机械:定时把当前日志文件改名,让应用重新生成一个新文件,然后再把旧的压缩、删除,循环往复。

4.1 logrotate 的核心机制:切换而不是删除

logrotate 的核心是“切换”旧文件,而不是直接删除最新文件。默认流程是这样的:比如/var/log/nginx/access.log到轮转周期了,logrotate 先把它改名为access.log.1,然后通知 Nginx 重新打开一个新的access.log文件。等到下一次轮转,access.log.1变成access.log.2,新生成的access.log变成access.log.1,依次类推。

这样做的好处是,在任何时刻,最新日志都在固定的access.log文件里,监控脚本、日志采集器不用频繁改路径。

如果应用自己没有处理信号的能力,logrotate 里配置了copytruncate,那就是另一条路:先把当前日志文件复制一份,然后立刻把原文件清空。这会导致复制过程中新写入的一些日志行被截掉,算是这个方式的天然损耗。要不要用 copytruncate,就看应用懂不懂 syslog 那一套重新打开文件的协议了。

判断的标准其实很简单:能主动响应 SIGHUP 或 USR1 信号重新打开日志文件的应用,比如 Nginx、Apache,用 create 方式;不能响应信号、只能傻傻往同一个文件句柄里写的应用,比如某些 Java 服务、Nginx 的 access_log 如果没开启postrotate重载,就用 copytruncate 兜底,但在高并发下丢十几行日志也属于可接受范围。

4.2 参数别乱选:create、copytruncate、compress、dateext 的区别和适用场景

logrotate 参数看着多,真正需要理解的核心就几个。我整理了一张对照表,方便你按场景选:

参数作用适用场景
rotate 7保留 7 个轮转后的旧日志需要预留一段可查周期
daily/weekly/monthly轮转周期,按天/周/月日志增长快就 daily,慢就 weekly
compress旧日志用 gzip 压缩节省磁盘空间,需压缩时间
delaycompress延迟一轮再压缩配合 create 轮转时,避免刚轮转的旧文件还在被写入就压缩
copytruncate先复制后清空原文件应用不能重开日志文件时使用
create 0640 root adm轮转后新建日志文件并设置权限默认动作,保证新文件权限正确
dateext用日期命名轮转文件,比如 access.log-20250101避免文件名覆盖
missingok日志文件不存在时跳过,不报错服务未启动时避免误报
notifempty文件为空时不轮转避免产生大量空文件
postrotate/endscript轮转后执行脚本通知应用重开日志、重载配置

核心参数里最值得说的是dateext。默认情况下 logrotate 用access.log.1access.log.2这种序号命名,一旦超过rotate设置的数量,最老的文件会被覆盖;而打开dateext之后,备份文件会变成access.log-20250101这样的格式,一眼就能看出是哪天的日志,排查问题时省太多时间了。

压缩的选择也很有讲究。compress确实能大幅省空间,但如果在轮转当天旧文件还在被某些进程引用(比如 copytruncate 模式下写入方还没来得及关句柄),直接压缩会导致数据丢失。稳妥的组合是compress加上delaycompress,把压缩推迟到下一轮轮转时执行,让上一轮的旧文件先留着一份未压缩的副本,确保安全性。这一点在很多数据库日志配置里有过血泪教训,我建议你直接按这个组合用,不要为了省那点空间冒险。

4.3 应用自定义日志轮转的几个实战例子

光讲参数容易头晕,直接贴几个我配过的场景。先看 Nginx,这是一个非常标准的“支持信号、适合 create + postrotate 重载”的例子:

cat > /etc/logrotate.d/nginx << 'EOF' /var/log/nginx/*.log { daily rotate 14 compress delaycompress dateext missingok notifempty create 644 www-data www-data sharedscripts postrotate [ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid) endscript } EOF

这段配置的意思是:Nginx 的日志每天轮转一次,保留 14 个旧文件,用日期命名,压缩延迟一轮,轮转后给 Nginx 主进程发 USR1 信号让它重新打开日志文件。kill -USR1这个信号是 Nginx 官方支持的重开日志机制,通过 postrotate 调用,保证新的 access.log 立即生成。

再看一个 PostgreSQL 的例子。PostgreSQL 本身有自带的日志轮转设置,但如果想用统一的 logrotate 管理,就需要注意它默认不响应外部信号,所以用 copytruncate 更保险:

cat > /etc/logrotate.d/postgresql << 'EOF' /var/log/postgresql/*.log { weekly rotate 4 compress copytruncate missingok notifempty create 640 postgres postgres } EOF

copytruncate保证了即使 PostgreSQL 进程不重新打开文件,日志也能被清空重建。但代价就是高并发下会丢少量日志,这在这个场景可以接受,因为 PostgreSQL 本身还会把日志同时发给 syslog。

还有更细的用法:如果你的某个 Java 服务日志文件路径固定,但 Java 进程不响应任何信号,最简单的方案就是用 copytruncate 强行做轮转,然后在 postrotate 里不执行任何重载命令,让它自然为新文件句柄写日志。

4.4 手动触发和调试:别傻等 cron 了

logrotate 默认由 cron 驱动,一般一天跑一次。但你在配置完新规则之后,不手动执行一次怎么知道配置有没有问题?这里有两个调试命令是必须掌握的:

# 调试模式,只输出将要执行的动作,不真正执行 sudo logrotate -d /etc/logrotate.conf # 强制立即执行某个配置文件的规则,并输出详细信息 sudo logrotate -vf /etc/logrotate.d/nginx

-d是 dry-run,不会改任何文件,适合验证配置语法;-v是 verbose,打印完整执行过程;-f是 force,强制轮转,哪怕没到轮转时间也执行。我建议先-d确认没问题,再用-vf强制轮转一把并看输出,确认所有路径和命令都对,才算真正配置完成。

手动触发之后,检查/var/log/nginx/目录,你会发现生成了access.log-2025xxxx这样的文件,同时 nginx 正常运行。如果发现没有生成新日志文件,多半是日期格式、压缩命令或权限出了问题,-d模式输出里会直接提示。

还有一个小技巧你可能需要:cron 的调度进度一般在/etc/cron.daily/里,Ubuntu 默认的 logrotate 调度脚本在这里。如果你觉得 logrotate 周期不合适的,可以修改/etc/anacrontab里的时区设置,但一般不推荐乱动,保持默认就好。

5. 把三者串起来:日常排障和日志架构落地

前面把三个组件的原理和命令都讲了,但实际用的时候,你面对的往往不是一个组件,而是一条完整的日志链。这一节我把它们串起来讲一个常见的排障流程,再给一套可以直接落地的最小方案。

5.1 从一条报错到真相的完整排查链条

假设你部署的 Web 服务突然返回 502,你第一反应是看 Nginx 日志。此时你需要明白,Nginx 的 access.log 和 error.log 是它自己写的,默认配置下 journald 也能同步记录它的标准输出。你可以用journalctl -u nginx看最近的错误,也可以用tail -f /var/log/nginx/error.log看实时日志,两条路殊途同归。

接着往下追,如果发现是后端进程挂了,那就要看后端服务的日志。服务如果是 systemd 托管的,journalctl -u myservice是首选,因为它连服务启动时的环境变量、退出代码、内核报错都记录在内。如果服务自己写了/var/log/myservice.log,那就去查这个文件,它可能经过 logrotate 轮转出了myservice.log.1,可以用less打开对比。

到了这一层,你的排障动作大概是这样:

# 第一步,看服务最近的状态 systemctl status myservice # 第二步,看最近一小时的服务日志 journalctl -u myservice --since "1 hour ago" # 第三步,如果服务日志里没有有效线索,去查系统日志 journalctl -p err --since "1 hour ago" # 第四步,看对应的文本日志文件 tail -n 100 /var/log/myservice.log

整套流程的信息来源是 journald 和文本日志的交叉验证。有时候 journald 丢了部分记录,文本日志却能补上;有时候两者内容互相冲突,你就要停下来想想哪一个是故障发生前最后的真相。

还有一个我特别想强调的点:别忽略 rsyslog 的时间同步。日志最怕时间不对,如果机器时钟和历史服务器不一致,你查日志的时候会一头雾水。Ubuntu 上第一步就是检查timedatectl,确认时间同步状态是 “System clock synchronized: yes”。我经手过一台时间偏差了 8 分钟的服务器,排查日志时怎么都对不上错误发生的时刻,最后发现是 NTP 没配好。时间不准,再全的日志都是废的。

5.2 生产环境日志管理的最小可行方案

聊完整套原理,我直接给一份我自己在用的最小方案。适用于单台或几台服务器的场景,不需要大而全的日志平台,但能保证日志完整、可查、不炸磁盘。

第一步,开启 journald 持久化:

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

第二步,限制 journald 磁盘占用。修改/etc/systemd/journald.conf

[Journal] SystemMaxUse=500M SystemKeepFree=100M

然后重启 journald。

第三步,确认 rsyslog 正常工作:

sudo systemctl enable --now rsyslog

第四步,给关键应用配置 logrotate。比如系统自带的配置已经覆盖了/var/log/syslog这些,你要额外处理的是 Nginx、MySQL、你的应用日志。为每一个日志文件编写一个/etc/logrotate.d/下的规则。

第五步,加一条 crontab 定时任务,每周手动 vacuum 一次 journald 的老日志。虽然 journald 有 SystemMaxUse 自动限制,但很多长期运行的服务器上还是会出现意外占用,定时 vacuum 更保险:

sudo crontab -e # 每周日凌晨3点清理超过30天的日志 0 3 * * 7 journalctl --vacuum-time=30d

这套方案的核心思想是:journald 管实时查询,rsyslog 管文本归档,logrotate 管应用日志轮转,cron 管周期兜底。不需要很复杂,但能保证你在一台机器上,既不丢日志,也不怕磁盘被打满。

6. 踩坑记录与避坑心得

技术文章写多了,最值钱的其实是坑。我在日志管理上踩过的坑不少,这里挑几个高频的整理成速查表,再补充几句经验之谈。

6.1 高频事故速查表

现象可能原因解决方式
journalctl查不到老日志journald 未持久化,日志在内存中被清除或重启丢失创建/var/log/journal目录开启持久化
磁盘突然被打满journald 占用或某个日志文件无限增长journalctl --disk-usage查占用,logrotate -vf强制轮转应用日志
改完 rsyslog 配置不生效没重启 rsyslog,或规则顺序被更早的文件抢占sudo systemctl restart rsyslog,自定义文件用 50- 前缀
logrotate 轮转后应用日志仍写入旧文件应用没有重新打开日志文件,没触发 postrotate配置对应信号或改用 copytruncate
logrotate -d正常,-vf却报权限错误logrotate 以 root 身份执行时也创建文件权限不对检查 create 参数,手动修改目标目录权限
远程日志转发没反应防火墙没有放行 514/10514 端口放行端口;如果使用 TCP 请确认两端 imtcp 模块都加载
时间对不上,日志顺序混乱服务器时钟未同步,NTP 没配置执行timedatectl set-ntp true开启时间同步

这个表你打印出来贴在工位上,基本能解决日常 80% 的日志疑难杂症。

6.2 给新手的几个实用建议

第一个建议:不要把鸡蛋放在一个篮子里。journald 和 rsyslog 是两套相互独立但又有关联的体系,排查问题时两边都要看一眼,不要只盯着其中一个。文本日志适合快速查看,journalctl 适合精确搜索,两个配合起来效率最高。

第二个建议:所有 logrotate 配置改完,一定要手动跑一次 -d 和 -vf,不要等 cron 跑起来才暴露问题。我见过太多人配置完就扔那等着,结果一个月后磁盘被撑爆,打开 logrotate 日志一看全是语法错误。十分钟的调试,换来一个月的心安。

第三个建议:养成“日志分目录”的习惯。尽量让每个核心应用都往/var/log/下建独立子目录,并且配置独立的轮转规则。不要把所有日志都堆进 syslog,搜索的时候真的太费劲了。最后,如果日志量真的到了单机处理不了的程度,再去考虑引入 Elasticsearch 之类的日志平台,但在这之前,先把单机的 rsyslog + journald + logrotate 基础打好,比什么都强。

我自己这十几年摸服务器的一个最大体会是:日志系统就像保险,平时感觉不到它的存在,一旦出了事,它就是唯一的救命稻草。花一点时间把日志管理理顺,每一次故障排查都会快很多,而且你会在一次次对着日志揪出问题根因的过程中,真正建立对系统的掌控感。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 7:43:38

Flask实战指南:从轻量级应用到Docker部署的Python Web开发全流程

1. 为什么我推荐Flask&#xff1a;轻量级不是功能少&#xff0c;而是选择自由很多朋友第一次接触Flask时&#xff0c;都会有一个困惑&#xff1a;它的核心代码就那么几行&#xff0c;连个ORM、表单校验、后台管理都要自己装&#xff0c;这也能算一个完整的Web框架&#xff1f;我…

作者头像 李华
网站建设 2026/9/9 7:43:09

科技型中小企业申报:用软著补齐研发成果的实操指南

我先把大实话放在前面&#xff1a;这几年见过太多中小软件团队&#xff0c;产品做了一堆&#xff0c;项目文档也厚厚一沓&#xff0c;结果到了科技型中小企业申报的时候&#xff0c;研发成果列表拉出来却薄得可怜。为什么&#xff1f;不是没干活&#xff0c;而是活儿干完就散落…

作者头像 李华
网站建设 2026/9/9 7:42:56

diagram-design:HTML+SVG+Mermaid+draw.io四层架构实战

1. 什么是 diagram-design&#xff1a;不只是画图&#xff0c;而是信息结构的工程化表达 “diagram-design”这个词最近在前端、产品、架构和教学类项目里高频出现&#xff0c;但它绝不是简单地拖拽几个方框连几条线。我做可视化工具链支持和文档系统搭建有八年多&#xff0c;…

作者头像 李华
网站建设 2026/9/9 7:42:39

工业多协议网关选型:西门子与三菱异构系统通讯实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 7:42:05

fluid-player实战指南:HTML5流媒体播放器的集成与配置

简介&#xff1a;Fluid Player 是一款开源的大型 HTML5 视频播放器&#xff0c;旨在帮助前端开发者在不依赖 Flash 的情况下轻松集成视频播放能力&#xff0c;并应对 VAST 广告、流媒体等多类复杂需求。这份资源为完整项目压缩包&#xff0c;共 20 个文件&#xff0c;主体为 9 …

作者头像 李华
网站建设 2026/9/9 7:41:59

Python数据可视化实战:从工具选型到通信流量分析

干了这么多年数据分析&#xff0c;我一直觉得&#xff0c;数据可视化这件事&#xff0c;真正难的不是把图画出来&#xff0c;而是搞清楚你为什么要画这张图。很多人一上来就追求炫酷&#xff0c;恨不得把几十种图表堆在一个大屏上&#xff0c;结果老板看一眼就走了&#xff0c;…

作者头像 李华