Linux日志写入阻塞本质是日志进程因IO子系统瓶颈(磁盘慢、队列满、文件系统压力大或配置不当)而卡在不可中断睡眠状态,需从进程状态、IO负载、存储路径和日志配置四层排查。

Linux日志写入阻塞,本质是日志进程(如 rsyslog、journald 或应用自身)在尝试写入磁盘时被挂起,常见表现为服务响应变慢、日志延迟、甚至进程卡死。核心原因往往落在 IO 子系统——磁盘慢、队列满、文件系统压力大,或日志配置不当。排查需从进程状态、IO 负载、存储路径和日志机制四层切入。
看进程是否真在等 IO
用 ps -eo pid,ppid,comm,wchan:20,state,etime | grep 'D\|W' 找出处于不可中断睡眠(D)或等待内核函数(W)状态的进程。若 rsyslogd、systemd-journald 或你的业务进程长时间显示 D 状态,且 wchan 显示 ext4_writepages、xfsaild、blk_mq_run_hw_queue 等,说明它正卡在文件系统或块设备层写入环节。
进一步确认:用 cat /proc/<PID>/stack 查看该进程当前内核调用栈,能明确卡在哪一层(如 vfs_write → ext4_file_write_iter → ext4_writepages → submit_bio)。
查 IO 延迟与队列积压
运行 iostat -x 1 观察关键指标:
- %util 接近 100% 仅表示设备忙,不等于瓶颈;更要看 await(平均每次 IO 等待毫秒)> 10ms、r_await/w_await 显著升高,尤其 w_await 持续 > 50ms 表明写入严重延迟
- avgqu-sz(平均请求队列长度)持续 > 10,结合高 await,说明 IO 请求在队列中堆积
- svctm 已废弃,勿参考;用 r/s + w/s 和 await 反推实际吞吐压力
再用 iotop -oP 定位具体哪个进程/线程在刷脏页或写日志文件,注意区分是日志进程主动写,还是内核因脏页回收(pdflush/kswapd)被动刷盘导致的间接阻塞。
检查日志目标路径的底层存储
日志写入慢,常因目标路径所在设备性能差或配置不合理:
- 确认日志目录(如 /var/log 或 /var/log/journal)是否挂在机械盘、低配云盘、或共享存储(如 NFS/CIFS)上——这些本身延迟高、IOPS 低,禁用日志同步(sync=off)也难缓解
- 检查文件系统挂载参数:data=ordered(默认)比 data=writeback 更安全但写开销略大;若使用 XFS,确认未启用 logbsize 过小或 logbufs 不足导致日志区争用
- 用 lsblk -d -o NAME,ROTA,RQ_SIZE,SCHED 查旋转磁盘(ROTA=1)、队列深度(RQ_SIZE)、IO 调度器(SCHED)。SSD 应设为 none 或 kyber,机械盘可试 bfq;避免 cfq(已废弃)或调度器被锁死
审视日志服务配置与写入模式
配置不当会放大 IO 压力:
- rsyslog:检查 $ActionFileDefaultTemplate 是否含大量模板解析;禁用 $ActionFileEnableSync on(强制每次写都 fsync);改用异步队列:$ActionQueueType LinkedList + $ActionQueueFileName + $ActionResumeRetryCount -1
- systemd-journald:确认 Storage= 设置合理(persistent 写磁盘,volatile 仅内存);限制大小:SystemMaxUse=512M 防止 journal 占满磁盘;关闭压缩:Compress=no 减少 CPU+IO 开销
- 应用直写日志:避免高频小 write() + fflush();改用行缓冲或全缓冲,批量写入;敏感场景考虑异步日志库(如 spdlog 的 async logger)或通过 socket 转发给 rsyslog










