先看iostat -x 1中%util是否持续>90%且wkb/s异常高,再结合iotop -o确认rsyslogd/journald等进程write-heavy,同时await>50ms、avgqu-sz>2表明写不下去而非单纯写得多;再用df -h和df -i查/var/log分区空间与inode是否耗尽;最后用lsof +d /var/log定位具体写日志的进程和文件。

怎么确认日志写入正在拖慢磁盘IO
先别急着查日志文件本身,得先看系统是否真被日志压垮了。核心判断依据是:iostat -x 1 输出中某设备的 %util 持续 >90% 且 wKB/s 异常高,同时 iotop -o 里能看到 rsyslogd、journald、logrotate 或业务进程(如 java、nginx)在持续 write-heavy。
注意:不是所有日志写入都等于瓶颈。关键要看 await 是否同步升高(>50ms 表明设备响应慢)、avgqu-sz 是否长期 >2——这说明写请求在队列里堆着,不是简单“写得多”,而是“写不下去”。
-
df -h看/var/log所在分区使用率是否 ≥95%,空间快满会触发 ext4 延迟分配失败,加剧 IO 阻塞 -
df -i查 inode 使用率,小文件日志场景下/var/log的 inode 耗尽比磁盘空间更早引发卡顿 - 运行
lsof +D /var/log 2>/dev/null | awk '$5 ~ /^REG/ && $9 ~ /\.log$/ {print $1,$2,$9}' | sort -k2 -n | uniq -c | sort -nr,快速列出当前正往/var/log写日志的进程和文件
为什么journalctl -f或tail -f本身也会加重IO负担
实时日志监控工具本身不是只读,它们会强制刷新、频繁 stat、甚至触发 page cache 回写。尤其当 systemd-journald 日志量大时,journalctl -f 会持续 poll journal 文件,叠加 tail -f 对多个大日志轮转文件做 inotify 监控,导致大量小 IO 和元数据操作。
这不是 bug,是设计使然:journald 默认启用 Storage=persistent,且日志索引更新、压缩、rotate 都需要同步刷盘;tail -f 在 ext4 上对已删除但未关闭句柄的日志(lsof +L1 可见)仍会尝试 read,产生无效等待。
- 临时缓解:停掉
journalctl -f和tail -f,用less +F /var/log/syslog替代(它不主动轮询) - 检查 journald 配置:
/etc/systemd/journald.conf中RateLimitIntervalSec=30和RateLimitBurst=1000是否过松,高频日志会触发限流并堆积缓冲区 - 避免在生产环境用
tail -f /var/log/*.log—— glob 展开会打开数百个文件描述符,每个都占用 inode 缓存和 inotify watch
如何定位具体哪个日志文件或服务在疯狂刷盘
不能只靠文件大小排序,因为有些日志是循环覆盖的(如 journal),有些是刚清空但句柄未释放(deleted 状态)。真正有效的办法是结合内核视角和进程打开文件行为。
执行 sudo lsof -nP +D /var/log 2>/dev/null | grep -E 'REG.*[[:space:]]+[^[:space:]]+\.log' | awk '{print $1,$2,$9}' | sort | uniq -c | sort -nr,输出类似:
287 nginx 12345 /var/log/nginx/access.log 192 java 67890 /opt/app/logs/app.log 87 rsyslogd 23456 /var/log/messages
再针对 PID 查详细:sudo lsof -p 67890 | grep -E '\.log|\.out$',确认是否在写滚动日志、debug 级别日志、还是异常堆栈反复 dump。
- 重点关注
SIZE列持续增长的文件,而非du -sh最大的——后者可能是旧归档,前者才是活源头 - 用
strace -p PID -e trace=write,fsync,fdatasync -s 128 2>&1 | head -20看进程是否在每条日志后都调用fsync,这是最典型的 IO 慢因 - 检查应用配置:Java 应用的 logback.xml 是否设了
<immediateflush>true</immediateflush>,Nginx 的access_log是否带buffer=64k flush=1s
日志IO瓶颈修复中最容易被忽略的点
很多人调大日志轮转周期、关掉 debug 日志就以为完事了,但真正卡住系统的往往是底层机制没对齐:ext4 延迟分配在高并发小写场景下竞争激烈,journal 提交频率与磁盘物理延迟不匹配,或者日志路径落在 LVM 快照卷上——这些不会报错,但会让 %util 持续 99% 且 await 波动剧烈。
-
/etc/fstab中给/var/log分区加noatime,commit=30,减少元数据更新压力;若用 SSD,可试barrier=0(仅限有断电保护的存储) - 对 Java 应用,把日志输出重定向到
AsyncAppender或Disruptor,避免主线程阻塞在write系统调用 - 禁用 journald 的
ForwardToSyslog=yes(默认开启),否则日志会双写:一次进 journal,一次进 rsyslog,IO 翻倍 - 不要只清理
/var/log下的文件,用lsof +L1 | grep log找出那些已被logrotaterename 但进程还没 reload 的 deleted 日志,kill -USR1 通知服务 reopen 日志文件











