恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Linux日志管理实战:journalctl、logrotate与磁盘清理指南
首页
资讯中心
/
Linux日志管理实战:journalctl、logrotate与磁盘清理指南
Linux日志管理实战:journalctl、logrotate与磁盘清理指南
发布时间:2026/10/11 19:18:17
各位折腾 Linux 的朋友不知道你们有没有遇到过这种场景磁盘告警了一顿排查下来发现/var/log占了好几个 G甚至把根分区直接塞满或者排障的时候想找某个服务的日志结果发现关键时间点的记录早就被覆盖得干干净净还有一种更头疼的日志文件明明还在但du和df看到的结果完全对不上。这些问题的根源都指向同一个东西——日志管理。我很久之前一直觉得日志嘛不就是程序把内容往文件里一写完事了。直到有次生产环境出问题我需要靠日志定位故障点结果发现日志被轮转覆盖、裁剪得面目全非那一刻我意识到日志管理是一项需要系统性对待的工程。这篇学习日志我就把我在 Linux 下折腾日志管理的完整思路、实操过程和踩坑记录整理出来从日志分类、核心工具原理到日志轮转配置、磁盘空间释放技巧再到常见故障排查一次性讲清楚。1. 日志体系全景Linux到底在记录什么1.1 日志不是日志文件那么简单很多人在接触 Linux 日志时第一反应就是“日志 文本文件”这个理解不能算错但太片面了。在 Linux 系统里日志的产生和存储路径大致分两派一派是传统 syslog 体系把各类程序运行信息通过 syslog 接口统一交给rsyslogd服务再由它按照规则分发到/var/log下的不同文件另一派是 systemd 引入的 journal 体系由systemd-journald把内核、服务、启动过程等信息集中记录日志以二进制格式持久化在/var/log/journal里。这里有个关键点journal 和 syslog 并不是互斥的很多发行版上它们同时在工作。journald 负责收rsyslog 也在收然后各写各的。所以你会看到/var/log/messages里有内容journalctl里也有内容但两者可能略有差异。这个差异不是 bug而是两条采集链路导致的正常现象。但这还没完。应用程序自己还会打日志比如 Nginx 的 access log 和 error log、应用框架自己写的业务日志、Java 应用的 GC 日志、数据库的慢查询日志等。这些日志有的走 syslog有的是直接写文件有的两者兼顾。所以日志管理要面对的是一个混搭生态不是单一工具能全覆盖的。理解了这一点你就能明白为什么日志管理方案需要组合拳journalctl 管 systemd 日志rsyslog 管传统 syslog 日志收集logrotate 管所有日志文件的轮转压缩第三方工具管应用自身日志采集。1.2 日志文件的分类与存放路径我手动梳理了一下 Linux 系统里常见的日志文件和它们的用途整理成了一张速查表方便对照查看日志文件路径主要记录内容重要程度/var/log/messages系统级通用日志很多服务的运行信息都会记录在这里高/var/log/syslog与 messages 类似Debian/Ubuntu 系常用高/var/log/secure认证与安全相关日志包括登录尝试、sudo 操作高/var/log/auth.log认证日志Debian/Ubuntu 系对应 secure高/var/log/boot.log系统启动过程日志中/var/log/dmesg内核环形缓冲区日志硬件驱动信息中/var/log/croncrontab 计划任务执行日志中/var/log/nginx/access.logNginx 访问日志不属于系统日志是应用自建中/var/log/nginx/error.logNginx 错误日志中/var/log/journal/systemd-journald 的二进制日志库高这只是最基础的清单每台机器实际内容会因安装的服务不同而不同。我建议你拿到一台新服务器之后第一件事就是ls -alh /var/log/看看整体大小和文件分布做到心里有数。这里我想多说一句/var/log/dmesg。你可能听说过dmesg命令它用来查看内核环形缓冲区的输出。其实/var/log/dmesg只是系统启动早期把 dmesg 内容保存下来的一个快照文件它不会持续更新。真要排查内核级问题要跑dmesg -T看实时缓冲或者看 journal 里的 kernel 相关记录。1.3 为什么不建议随手删日志有一种观点我觉得需要纠正日志可以删但要用正确的方式删。我见过有人排障空间不足时直接rm -rf /var/log/messages当场是释放了空间但后患很多。大部分服务进程会一直持有着日志文件的文件句柄file descriptor你把文件rm掉了进程还往那个句柄里写数据照样写进磁盘但你再也没有办法用常规方式读取或定位那个文件空间也一直释放不了必须重启进程才能真正释放。更常见也更危险的情况是日志文件是排障的唯一线索。你把日志删了等于把案发现场给破坏了。尤其是安全审计、故障复盘这类场景日志是根本依据丢了就没法溯源。所以正确做法是让日志轮转log rotation而不是直接删。本质上这是一个理念转变日志管理追求的是按需保留、自动压缩、过期清理而不是靠人肉去删。2. 核心工具解析journalctl、rsyslog 与 logrotate 三驾马车2.1 journalctl查看 systemd 日志的正确姿势journalctl是 systemd 体系里最核心的日志查询工具。它的数据源是/var/log/journal目录下的二进制 journal 文件而不是传统的文本日志。我第一次用journalctl的时候觉得这命令也太简单了直接journalctl -xe就能看到最近的错误信息。但用得越深入越发现这工具功能其实很强只是很多人没用到位。几个我日常频率很高的用法# 查看最近 30 分钟内的日志 journalctl --since 30 min ago # 查看某个服务单元的日志 journalctl -u nginx.service # 查看指定时间段的日志 journalctl --since 2026-01-20 08:00:00 --until 2026-01-20 10:30:00 # 只看某个优先级以上的日志0-7数字越小越紧急 journalctl -p err # 跟随模式类似 tail -f journalctl -f这里我想特别讲一下优先级过滤。journal 日志每条都有一个 priority 字段对应 syslog 的 emerg0、alert1、crit2、err3、warning4、notice5、info6、debug7。-p err会同时包含比 err 更严重的 emerg、alert、crit相当于“看所有错误级以上的日志”。排查问题时这个参数能快速过滤掉大量无用信息不要光看末尾 50 行就下结论。还有一点值得一提journalctl -xe里那个-x是显示解释信息-e是跳到日志末尾。这俩组合起来就像“直接翻到账本最后一页看最近发生了什么”应急排障时的效率非常高。journald 的配置文件在/etc/systemd/journald.conf。默认情况下日志存在内存还是磁盘由Storage选项决定。默认值通常是auto也就是“如果/var/log/journal存在就持久化否则只写内存”。很多刚装好的系统并没有/var/log/journal目录这意味着日志只在内存里一旦重启历史日志全部消失。如果你希望日志持久保留务必执行mkdir -p /var/log/journal systemctl restart systemd-journald2.2 rsyslog传统日志的收集与转发中枢rsyslog 作为 syslog 的增强版承担着传统日志体系里收集、过滤、转发的核心角色。它的配置文件在/etc/rsyslog.conf/etc/rsyslog.d/目录下面还能放分片的配置文件实现模块化管理。rsyslog 的配置逻辑可以理解为一个三要素模型输入源 过滤条件 动作。比如系统默认配置里这一行*.info;mail.none;authpriv.none;cron.none /var/log/messages拆开看就是所有 info 级别以上的日志但排除 mail、authpriv、cron 这几类的日志最终写入/var/log/messages。如果我想把某个应用的日志单独收集到独立文件里可以这样配置# /etc/rsyslog.d/myapp.conf if $programname myapp then /var/log/myapp.log保存配置后执行systemctl restart rsyslog然后往 logger 里写一条测试消息logger -t myapp This is a test log entry过两秒再去cat /var/log/myapp.log应该能看到记录。rsyslog 还承担着一个更重要的任务日志转发。在多机环境下把日志统一汇总到一台日志服务器上是运维中的常规操作。配置方式是增加一个远程目标*.* 192.168.1.100:514这个配置把所有日志通过 UDP 514 端口转发到 192.168.1.100。如果走 TCP用两个*.* 192.168.1.100:514通常我会用 TCP 而不是 UDP因为 TCP 有确认机制日志不容易丢。日志转发在生产环境里价值很大尤其是排查跨节点问题的时候统一日志入口能省下大量来回切换机器的时间。2.3 logrotate让日志文件不爆盘的自动轮转机制logrotate 是 Linux 下日志管理最重要的一个机制基本没有之一。它的存在就是为了回答一个问题日志文件越来越大怎么办logrotate 的工作原理不复杂由一个 cron 任务多数发行版放在/etc/cron.daily/logrotate每天执行一次logrotate命令根据配置决定哪些日志需要轮转、压缩、删除或重组。核心配置路径有两个全局配置/etc/logrotate.conf以及分应用配置/etc/logrotate.d/目录下的各个文件。来一段最典型的配置模板我自己经常这么写# /etc/logrotate.d/myapp /var/log/myapp.log { daily rotate 7 compress delaycompress missingok notifempty copytruncate create 0644 root root }逐项解释daily按天轮转当然还可以是weekly、monthly、hourly。rotate 7保留 7 个轮转后的旧日志文件。超过 7 份后最旧的会被删除。compress对轮转后的旧日志进行 gzip 压缩。delaycompress最新轮转出的一份暂不压缩等到下一轮轮转时再压缩。为什么要加因为有些程序还在往旧文件里写日志立刻压缩可能导致内容丢失拖延一个周期就安全很多。missingok日志文件不存在时不要报错继续往下执行。notifempty日志文件为空时不触发轮转。copytruncate先复制一份当前内容到轮转文件再把原文件截断。这个选项对有特定写日志行为的程序很重要通常配合应用使用比如 Apache、Tomcat。create轮转后重新创建一个新的空日志文件并设定权限。这里我建议所有人在配置 logrotate 之前先运行一下检查和演练# 调试模式查看执行过程但不真正执行 logrotate -d /etc/logrotate.conf # 强制执行即使未到轮转周期 logrotate -f /etc/logrotate.conf # 仅对某个配置执行 logrotate -f /etc/logrotate.d/myapp实际场景里有一个坑copytruncate和create其实是两套策略一般只用一种。copytruncate适合那些持续持有文件句柄的程序比如 Nginx、Python 应用因为它不改变原文件的 inode只是把内容复制之后清空程序写入不受影响。而create是直接把原文件改名成轮转文件然后新建一个原名的文件适合 syslog 这类会重新打开日志文件的服务。对大多数应用我倾向于用copytruncate因为它对应用写日志的影响最小副作用是复制和截断之间存在极短的时间窗口可能丢一点点日志但对绝大多数场景可以接受。3. 实操过程从零搭建一套完整的日志管理方案这一节我按照一个比较标准的实战流程来写适合刚拿到一台 Linux 服务器、什么都不管先保证日志不失控的场景。整体分四步查看现状 → 配置轮转 → 接入统一管理 → 定期巡检。3.1 第一步先搞清楚当前日志的占用情况拿到服务器之后第一件事是盘点日志资源占用。我一般会先跑这样一组命令# 查看 /var/log 目录所有文件及其大小按块数排序 du -sh /var/log/* # 查看日志目录整体占用 du -sh /var/log # 查看磁盘分区占用 df -h # 查看哪些日志文件最大 find /var/log -type f -size 100M -exec ls -lh {} \;这组命令能快速定位大头。有一回我检查某台业务服务器发现/var/log/nginx/access.log已经 8.7G就是业务量大了之后没人管轮转导致的。还有一次是/var/log/journal占用了 4 个 G因为 journald 默认对日志大小没有做限制系统跑了一年日志全留了下来。如果只是应急排障可以用tail或less去瞄一眼内容但盘点大小用du更靠谱。ls -lh看到的单个文件大小和du -h看到的可能有差异这是因为du统计的是磁盘实际占用块而ls显示的是文件逻辑长度这在稀疏文件上体现得很明显。日志文件很少是稀疏文件但总会有特殊情况。3.2 第二步配置 logrotate 轮转策略盘点完成后接下来就是给关键日志配置轮转策略。我建议的落地顺序是先配置全局默认参数再针对不同服务的日志配置个性化策略。我的做法是维护一个配置规范日志类型轮转频率保留份数是否压缩是否 copytruncateNginx 访问日志daily14是是应用业务日志daily30是是系统 messagesweekly4是否journal 日志按容量保留 500M不适用不适用针对 Nginx 的配置比较典型因为 Nginx 的 master 进程会保持日志文件的句柄不关闭如果用默认的create方式轮转后 Nginx 还会继续往旧文件已改名的文件里写日志新文件永远不会被写入。必须用copytruncate或者用nginx -s reopen通知 Nginx 重新打开日志文件。这是我要重点提醒的logrotate 的 postrotate 脚本就是用来干这个的配置里可以这样写/var/log/nginx/*.log { daily rotate 14 compress delaycompress missingok notifempty sharedscripts postrotate [ -f /var/run/nginx.pid ] kill -USR1 cat /var/run/nginx.pid endscript }kill -USR1是 Nginx 专门用来重新打开日志文件的信号。这个操作比copytruncate更干净不丢日志也是官方推荐的方式。对于 Java 应用、Tomcat、Python 程序这类不好发信号重新打开文件的场景用copytruncate更合适因为它不需要程序配合直接复制截断程序无感知。3.3 第三步将关键应用日志接入统一管理如果应用本身就是写文本日志的你只需要做好两点控制写到哪里、轮转规则是什么。但如果你用的是 systemd 管理的服务还可以让应用的 stdout 日志直接汇入 journal然后用journalctl统一查询。systemd 服务里只要不配置StandardOutput默认 stdout 就会进入 journal。这意味着你systemctl start myapp之后journalctl -u myapp.service就能看到服务的所有输出。这种模式的优点是日志采集完全自动不需要应用依赖 log4j 这类框架做文件输出配置。缺点也明显如果 journal 本身不持久化重启就丢。所以我建议的落地方案是混合模式对所有 systemd 服务确认 journal 持久化已开启。对需要长期保存或者要转给日志平台的关键业务日志应用自己写文件同时用 logrotate 控制轮转。对系统级日志保留 syslog 体系确保/var/log/messages、/var/log/secure这些常规文件持续有数据。这样做的原因很实际日志查询工具链里journalctl对单个 unit 的过滤很便利但做跨主机采集、接入第三方日志平台时绝大多数时候还是基于文件路径去采集的journal 的二进制格式接入成本高。所以保留 syslog 文件和日志平台的兼容性是我们必须留的后路。3.4 第四步定时巡检与日志分析配置完成后日志管理不能一劳永逸。我见过太多例子配置了 logrotate但 sh 脚本路径不对、权限不对结果轮转从来没正常执行过。日志管理方案的落地最后一步是巡检机制的建立。可以用简单的方式# 手动执行一次轮转看有没有报错 logrotate -f /etc/logrotate.conf # 查看 logrotate 是否有执行记录 cat /var/log/logrotate.log 2/dev/null || true # 查看系统 cron 日志里 logrotate 是否有执行 grep logrotate /var/cron/log 2/dev/null || grep logrotate /var/log/cron如果发现 logrotate 没有执行最常见的原因是配置文件里路径写错了、权限不足、/etc/cron.daily里的脚本没有可执行权限。把这三项逐个排除掉大部分问题都能解决。我还习惯把日志分析做成一个每日简短的检查脚本比如统计访问量前 10 的 IP、错误日志出现频率等。这个环节能让你真正做到“主动发现问题”而不是等告警响了再被动应对。举一个最基础的例子# 统计今天的异常 HTTP 状态码 awk {print $9} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20日志管理其实是可以和日常巡检、容量规划联动起来的。日志增长速度决定了磁盘扩容的节奏这一步做好了运维就稳了一大半。4. 常见问题与排查技巧实录这一节来聊聊我在日志管理实操中遇到的典型问题每一条都是实际踩过的坑。4.1 日志文件删除后空间不释放这是新手最容易碰到的问题我也栽过一次。现象是du -sh /var/log/messages显示文件大小只有几 K但df -h看根分区依然爆满。原因就是之前说的文件句柄问题某个服务进程比如 rsyslogd一直持有着被删除的文件句柄文件虽然从目录里看不到了但在磁盘上依然有对应空间占用只是没有文件名了。排查方法# 找出持有已删除文件句柄的进程 lsof | grep deleted输出里能看到类似这样的行rsyslogd 1234 root 12w REG 253,0 2147483648 123456 /var/log/messages (deleted)这里的/var/log/messages (deleted)说明这个文件被 rsyslogd 打开后又被删除了但进程还在写它。解决思路有几个从轻到重通过kill -HUP pid或systemctl restart rsyslog让服务重新打开日志文件最安全优雅。如果是临时文件可以直接重启对应服务。实在无法重启服务的情况下可以考虑复制/proc/pid/fd/12的内容到原路径下但操作风险高不推荐新手尝试。这类问题最好的防备就是不要直接rm日志文件让 logrotate 处理。4.2 journal 日志疯狂膨胀journald 的日志默认不限制大小如果你开了持久化时间久了磁盘空间会被慢慢吃掉。这个问题在我当时配置日志管理时最先暴露出来。journald 的配置里有两个关键参数SystemMaxUse1G SystemMaxFileSize200MSystemMaxUse指定 journal 持久化日志总容量的上限SystemMaxFileSize指定单个 journal 文件的最大大小。生产环境里我建议强制设置这两个值免得日志把磁盘搞挂。配置完要重启 journald 并清理旧日志systemctl restart systemd-journald # 清理 journal 日志到 500M 大小 journalctl --vacuum-size500M # 清理超过 7 天的日志 journalctl --vacuum-time7d--vacuum-size和--vacuum-time是清理 journal 的工具。这两个参数可以按需混用。注意这俩参数是直接清理没有恢复选项用之前一定确认数据不再需要。还有个小细节journalctl --vacuum-size500M并不是刚好把总量减到 500M而是会尽量逼近这个目标。执行完用journalctl --disk-usage查看当前占用。4.3 日志时间不同步导致排障困难这个问题应该被列进日志管理的隐藏坑。如果系统时间和日志采集时间不一致排障时很难对齐时间线。我处理过一起案例某系统日志记录的时间和实际业务异常发生时间差了 8 个多小时排查时如果没有换算时区很容易被误导。实际情况是服务器时区没设置正确或者当年经常遇到的系统时间漂移问题。日志写入的都是系统当前时间而系统时间错了日志自然就错了。所以日志管理的底层前提是时间同步。务必确认 NTP 或 chrony 服务正常运行# 查看当前时间 date # 查看时区设置 timedatectl # 查看时间同步服务状态 timedatectl status # 查看chrony服务同步状态 chronyc tracking如果你用 journald配好之后journalctl --utc可以统一用 UTC 输出时间这在跨时区排障时非常有用。我自己在日志分析场景下习惯统一转成 UTC避免不同机器时区不同导致的误判。4.4 日志过多被内核限制还有一个很容易被忽略的坑/var/log所在文件系统的 inode 耗尽了。日志文件数量特别多、单个文件特别小的时候磁盘可能还有空间但 inode 用完了导致所有新建文件直接失败表现为“磁盘空间不足但df -h显示还有空间”。这时候要跑df -i看 inode 使用率。如果 inode 满了解决办法是删除无用的小文件以及调整 logrotate 策略把轮转旧文件的保留数量降低。inode 的问题在日志量大的机器上出现概率其实挺高因为大量日志文件都是小文件比如 cron 的轮转文件、journal 的分片文件。所以检查日志管理方案时一定要把 inode 检查纳入常规巡检项。5. 日志管理方案的进阶心得与最终建议日志管理做到基础轮转和统一查看只能算及格。要做得好还需要思考几个更深入的点。第一日志不是你自己的私有财产。你的服务器出了故障如果日志分散在一台台机器里别人同事、下游团队、甚至是未来的自己去排障时唯一的路径就是逐台登录、逐个路径翻找。我强烈建议至少在关键节点做统一的日志聚集哪怕是简单地把关键日志 push 到同一台日志服务器。之后再进阶到日志平台如 ELK 这类开源方案也只是在收集端做扩展而已。第二日志保留策略没有万能模板。开发环境的日志可以只留 3 天生产环境的重要业务日志至少要留 30 天安全类日志建议留 90 天甚至更长审计要求严格的环境可能要按年度归档。保留时长必须和业务合规、排障需求对齐不要一味为了省空间把日志时间缩得很短。我的习惯是先规定最低保留要求再通过容量评估确定磁盘规划。第三轮转配置完成后一定要验证。配置完 logrotate 不验证等于白配。我自己的验证步骤很简单查看/var/lib/logrotate/status文件看轮转是否在按预期时间执行再配合跑一次logrotate -f观察日志是否真的生成了轮转文件。第四日志内容本身的质量也很关键。程序里输出的日志信息过于随意比如全部打print会导致日志量大但信息密度低。从这个角度来看日志管理和程序开发是联动的日志级别要不要分级、关键路径要不要打点、报错时要不要带上下文参数这些设计层面的问题在日志管理方案里也要提前想清楚。基础日志框架里常见的 info/error/debug 分级就是为此服务的。以我个人的操作为例日志管理方案不是一步到位的。我起初只配置了 logrotate保证磁盘不爆后来加了 journal 持久化并设置了容量上限再后来又整理了 syslog 转发把多台机器的日志归拢到一处。每一步都是被实际故障逼出来的。这里我给所有刚开始做日志管理的朋友一句真心话宁可前期多花一点时间把日志目录、轮转策略、保留周期、巡检项目写清楚也不要等出事了再去翻日志那时候你会后悔当初为什么偷懒。有一个小技巧可以分享给大家给/etc/logrotate.d/目录下的每个配置文件都写清注释注明这个轮转策略针对什么服务、为什么用这个保留周期、是否有 postrotate 脚本以及它的作用。过几个月回头看这些配置你会庆幸当时留了说明。另一个是别忘记定期ls -alh /var/log/扫一眼日志文件的增长趋势是系统健康的晴雨表观察多了你自然会对“正常增长”和“异常膨胀”产生直觉。这就是我这次日志管理学习的全部内容了。日志管理看似是运维里最不起眼的一环但它直接决定了系统出问题时你还有没有“现场还原”的能力。把这件事做扎实比用再花哨的监控工具都管用。