最准方式是直接检查 /proc/*/fd 中哪些进程正通过 fd 1 或 2 写入日志文件,结合 lsof +d /var/log 统计写操作进程,再用 ls -l /proc/pid/fd/ | grep -e '1|2|\.log$' 定位具体输出目标。

怎么快速定位高频写日志的进程
直接看 /proc/*/fd 里哪些进程正往文件描述符(尤其是 1、2)写大量内容,比盲扫日志文件更准——因为很多服务会重定向 stdout/stderr 到日志,但不一定会立刻 flush 到磁盘,lsof 或 ls -l /proc/*/fd/* 能抓到“正在写”的实时状态。
实操建议:
- 运行
sudo lsof +D /var/log 2>/dev/null | awk '$5 ~ /^w/ {print $2}' | sort | uniq -c | sort -nr | head -10,列出对/var/log下文件有写权限(w)的 top 10 进程 PID - 对可疑 PID,查它当前打开的 fd:
ls -l /proc/<pid>/fd/ 2>/dev/null | grep -E '1|2|log|\.log$'</pid>,重点看是否连着/dev/pts、pipe或某个增长飞快的日志文件 - 如果看到
anon_inode:[eventpoll]或socket占多数,说明它可能不是直接写日志,而是通过 syslog 或 journald 中转,得切到下一节查
systemd-journald 占用高时怎么确认源头
很多“狂刷日志”的表象其实是 journald 在缓存或转发日志,尤其当服务用 syslog() 或 stdout 输出、且 StandardOutput=journal 时,真正刷盘的是 journald 自己,不是原进程。
实操建议:
- 先看 journal 实时速率:
journalctl -o json --since "1 minute ago" | wc -l,如果每分钟超 5000 行,基本算异常 - 用
journalctl -o json --since "30 seconds ago" | jq -r '.SYSLOG_IDENTIFIER // .UNIT // "-"'抽出最近 30 秒日志来源,统计频次:... | sort | uniq -c | sort -nr - 查具体服务配置:
systemctl show <unit-name> | grep -E "(StandardOutput|StandardError|SyslogIdentifier)"</unit-name>,确认它是否把输出直送 journal,且没设RateLimitIntervalSec或RateLimitBurst
怎么判断是应用层逻辑打点还是配置错误
高频日志往往分两类:一类是代码里写了死循环 log.Info("x=%v", x),一类是配置错导致反复重试/告警(比如数据库连不上,每秒重连并记 error)。前者看日志内容重复度高、变量值不变;后者常带堆栈、时间戳密集、错误码一致。
实操建议:
- 对目标日志文件,用
tail -n 1000 /path/to/log | sort | uniq -c | sort -nr | head -5看最高频的几行——如果某行出现几百次,基本是无意义打点 - 用
grep -E "(error|ERROR|panic|failed|refused|timeout)" /path/to/log | tail -n 500 | awk '{print $1,$2,$3}' | sort | uniq -c查错误时间分布,如果集中在秒级精度(如Jun 05 14:22:01出现 20 次),大概率是失败重试 - 临时限制某服务日志量验证:
sudo systemctl set-property <unit-name> LogLevelMax=warning</unit-name>(需 systemd v240+),观察磁盘写入是否下降
别忽略 logrotate 和 sync 导致的假象
有时候你看到 du -sh /var/log/*.log 增长飞快,但 lsof 找不到对应写进程——可能是 logrotate 正在 copytruncate,旧文件句柄还被进程占着,新日志实际写进空文件;也可能是应用开了 O_SYNC 或频繁 fsync(),让小量日志引发大量磁盘 I/O。
实操建议:
- 检查
logrotate是否卡住:ls -lt /var/log/*.log* | head -5,看是否有.1、.2.gz但主文件大小不变,同时lsof | grep deleted里存在已删日志文件的残留句柄 - 用
strace -p <pid> -e trace=write,fsync,fdatasync -s 64 2>&1 | grep -E "(write|fsync)"</pid>抓真实系统调用,如果write(2, ...)每秒上百次但每次只写几十字节,就是 O_SYNC 类问题 -
iotop -oPa看实际磁盘写入进程,注意区分 “DISK WRITE” 和 “SWAPIN” —— 有些服务日志量不大,但因内存不足频繁 swap,看起来像在刷日志
最麻烦的情况是日志被重定向到管道或 socket(比如 2>&1 | logger),此时 /proc/<pid>/fd/</pid> 显示的是 pipe inode,得顺着 pipe:[123456] 反查另一端进程。这个链路容易断,建议优先从 journalctl -u <unit></unit> 或 rsyslog 的 /var/log/syslog 入手追源头。











