多语言外贸网站磁盘空间快速增长,如何从日志、inode和I/O延迟定位原因

磁盘空间快速增长时,先不要把“df使用率升高”直接等同于“网站文件变多”。Linux文件系统至少要区分三类问题:数据块接近耗尽、inode数量耗尽,以及存储I/O变慢。三者可能同时出现,也可能只有其中一种。
建议先在发生异常的服务器上记录以下信息,再进行清理或重启服务:文件系统类型与挂载点、容量使用率、inode使用率、目录占用、日志文件大小、是否存在已删除但仍被进程打开的文件,以及异常时段的I/O指标。没有这些基线,直接删除日志可能只能暂时降低占用,却无法解释增长来源。
“多语言外贸网站如何规划海外服务器节点和访问线路?”属于访问路径问题。对本次磁盘排查而言,节点或线路只能作为请求量、回源频率和日志写入量的外部变量,不能代替服务器本地的容量、inode和I/O证据。应先确认具体哪台服务器、哪一个挂载点在增长。
先分清三个指标分别说明什么
容量使用率不等于业务文件大小
df -h展示的是文件系统层面的已用空间,其中不仅包括网站代码、上传文件和日志,还包括文件系统元数据、其他目录、已删除但仍被进程占用的文件,以及部分文件系统保留空间。
du则更接近目录和文件层面的占用统计,但如果没有使用正确的挂载范围、权限不足或遗漏了隐藏挂载点,du与df可能明显不一致。
因此:
df高、du也高,通常是文件真实占用持续增加;df高、du明显低,优先检查已删除文件、其他挂载点、权限遗漏和文件系统元数据;df不高但网站无法创建文件,可能是inode耗尽,而不是容量耗尽;- I/O延迟高只说明读写操作变慢,不能单独证明磁盘空间已经不足。
inode是“文件数量额度”,不是容量
一个目录中存在大量小文件时,可能还没有占满容量,inode却已经接近耗尽。多语言网站常见的放大因素包括按语言生成的缓存文件、会话文件、缩略图、静态化页面、临时文件和细粒度的日志切片。
df -i中的IUse%接近满值时,即使df -h仍有可用空间,也可能出现以下现象:
- 无法创建新的缓存或上传文件;
- 日志轮转失败;
- 应用报“没有可用空间”,但目录大小看起来并不大;
- 部署过程中无法生成临时文件;
- 数据库或队列组件无法创建必要的运行文件。
inode问题的处理重点不是继续寻找“大文件”,而是找到数量异常的目录和文件类型。
I/O延迟是读写等待,不是访问线路延迟
I/O指标反映服务器存储设备或文件系统操作的等待情况,网站响应时间还可能受到应用执行、数据库查询、网络往返和并发排队等因素影响。
因此,await升高不能直接推出“用户访问一定变慢”,同样,网站访问变慢也不能只归因于磁盘。必须把I/O采样时间与应用日志、请求高峰、日志轮转和文件增长时间对齐。
第一步:确定异常发生在哪个文件系统
以下命令适用于常见Linux服务器,主要是只读查询。将/srv/www/site替换为实际网站目录;如果网站目录不存在,应先用pwd、部署配置或进程参数核对路径,不要直接猜测。
SITE_ROOT=/srv/www/site
date -Is
hostname
findmnt -T "$SITE_ROOT" -o TARGET,SOURCE,FSTYPE,OPTIONS
df -hT "$SITE_ROOT"
df -ih "$SITE_ROOT"
这些结果需要同时保存:
TARGET确认网站目录实际落在哪个挂载点;FSTYPE确认文件系统类型;df -hT查看数据块使用情况;df -ih查看inode使用情况;OPTIONS可以帮助判断是否存在只读挂载或其他特殊挂载参数。
如果网站位于/var/www,日志位于/var/log,两者可能并不在同一个文件系统。此时网站目录增长不一定会改变日志文件系统的使用率,反过来也一样。
用同一文件系统范围统计目录
sudo du -xhd1 "$SITE_ROOT" 2>/dev/null | sort -h
sudo du -xhd1 /var/log 2>/dev/null | sort -h
-x表示不跨越其他文件系统,能够避免du进入独立挂载点后把无关数据计算进去。若输出被权限错误截断,不能把结果当成完整统计,应使用具有读取权限的账户重新执行,并保留权限错误信息。
如果根目录本身也需要核查,应分层执行,避免一次扫描整台服务器造成额外I/O:
sudo du -xhd1 / 2>/dev/null | sort -h
sudo du -xhd1 /var 2>/dev/null | sort -h
sudo du -xhd1 /home 2>/dev/null | sort -h
df与du不一致时的判断顺序
| 现象 | 优先验证 | 通常说明 |
|---|---|---|
df和du都显示占用持续增加 | 大目录、日志、上传文件、缓存文件 | 文件仍然存在,属于真实数据增长 |
df很高,du明显偏低 | 已删除文件、独立挂载点、权限、文件系统元数据 | du没有看到全部已占用空间 |
df -h正常,df -i接近满值 | 小文件数量和目录层级 | inode资源先耗尽 |
单个文件ls -lh很大,但du占用较小 | 稀疏文件或文件块实际分配不同 | 逻辑大小与实际分配空间不同 |
| 网站目录不大,但根文件系统持续增长 | 其他目录、系统日志、临时目录 | 增长源不在网站目录本身 |
文件系统级别的统计优先于某一个目录统计。不要只根据网站目录的du结果判断整块磁盘是否安全。
第二步:从日志增长确认写入来源
先列出大文件,再判断增长速度
SITE_ROOT=/srv/www/site
sudo find /var/log "$SITE_ROOT" -xdev -type f \
-printf '%s %TY-%Tm-%Td %TH:%TM %p\n' 2>/dev/null |
sort -nr | head -n 50
该命令按文件字节数列出较大的文件,并显示修改时间。它能帮助定位候选文件,但只能说明当前大小,不能单独证明文件正在快速增长。
对候选日志应在两个时间点记录大小。例如在异常开始时和一段观察时间后分别执行:
sudo stat -c '%s %y %n' /var/log/example-access.log
sudo stat -c '%s %y %n' /var/log/example-error.log
如果日志发生轮转,不能只比较活动文件。应将活动文件、带序号的旧日志、压缩日志和应用自定义日志目录一起统计,否则可能把“活动文件变小”误判成“日志停止增长”。
日志增长常见于以下几类情况:
- 访问请求量增加,访问日志按请求数线性增长;
- 错误或警告被重复输出,单次请求产生多行日志;
- 调试级别被长期开启;
- 多语言路径、查询参数、来源信息或异常堆栈使单行日志变长;
- 日志轮转任务未执行、执行后未压缩或保留数量过多;
- 应用没有重新打开轮转后的日志文件,旧文件仍被进程持有;
- 系统日志和网站日志位于不同目录,实际增长源被遗漏。
这些判断都需要结合实际日志格式。不能看到访问日志变大,就直接认定是正常访问增加;爬虫重复请求、错误重试、健康检查和异常请求同样可能放大日志量。
检查系统日志和已删除文件
如果系统使用日志服务,可以先查看其占用情况:
sudo journalctl --disk-usage
该结果只覆盖系统日志服务管理的日志,不包括普通文本文件、应用自建日志目录或单独挂载的日志目录。
如果df显示空间已被占用,但du找不到对应文件,检查仍被进程打开的已删除文件:
sudo lsof +L1
输出中若出现较大的文件,并且文件名带有(deleted),说明目录项已经删除,但进程仍持有文件描述符。空间通常要等进程关闭该描述符后才会释放。
此时不要直接反复删除同一路径,因为目录项已经不存在。应先确认:
- 哪个进程持有文件;
- 该进程是否为网站服务、日志服务或其他关键组件;
- 是否支持平滑重载;
- 重启是否会影响正在处理的请求;
- 是否需要在低峰期执行。
重启服务属于有影响的操作,必须先确认配置、保存当前证据,并准备按现有运维流程回退。不能在不了解服务依赖的情况下使用通用重启命令。
检查日志轮转,而不是直接删除活动日志
如果服务器使用logrotate,可以先执行模拟检查:
sudo logrotate -d /etc/logrotate.conf
-d用于调试,通常不会真正轮转文件。重点观察:
- 配置文件是否被读取;
- 日志路径是否与实际路径一致;
- 是否存在权限错误;
- 轮转周期是否符合预期;
- 旧日志保留数量是否过多;
- 压缩、延迟压缩和重命名动作是否产生冲突。
如果需要查看更详细的执行信息,可以使用:
sudo logrotate -dv /etc/logrotate.conf
不要在未备份配置、未确认影响范围时直接使用logrotate -f。强制轮转可能立即重命名或压缩多个日志文件,也可能与正在运行的应用产生文件描述符问题。修改前应备份相关配置;如果修改后出现异常,恢复备份配置并按服务文档执行配置重新加载。
系统日志清理同样属于删除操作。例如journalctl --vacuum-time会删除符合保留条件的归档日志。执行前应确认组织的日志留存要求、是否需要备份以及是否允许丢失历史排障证据。删除操作通常不能依靠简单命令回滚,只能通过预先备份恢复。
第三步:判断是不是inode耗尽
确认文件系统的inode使用率后,应定位文件数量集中区域。先从较小的目录开始,避免在文件数量极大的路径上反复全量扫描。
SITE_ROOT=/srv/www/site
sudo find "$SITE_ROOT" -xdev -type f | wc -l
sudo find "$SITE_ROOT" -xdev -type d | wc -l
这两个统计分别近似反映普通文件和目录数量。它们不能替代文件系统的精确inode统计,但可以帮助判断数量是否集中在网站缓存、上传、临时或日志目录。
继续向下拆分:
sudo du -xhd1 "$SITE_ROOT/var" 2>/dev/null | sort -h
sudo du -xhd1 "$SITE_ROOT/storage" 2>/dev/null | sort -h
sudo du -xhd1 "$SITE_ROOT/cache" 2>/dev/null | sort -h
sudo du -xhd1 "$SITE_ROOT/uploads" 2>/dev/null | sort -h
以上目录只是常见示例,必须先确认真实路径。多语言网站如果为每个语言版本生成独立缓存或静态文件,文件数量可能按语言数、页面数和缓存版本数叠加增长;但这只是增长机制,是否存在问题仍要通过文件数量、创建时间和清理策略验证。
inode排查应关注三个维度:
- 数量集中在哪里:是缓存目录、上传目录、临时目录还是日志目录。
- 文件是否持续产生:比较不同时间点的文件数量和最早、最新修改时间。
- 是否存在无限增长机制:例如没有过期策略、失败任务重复生成、临时文件异常残留。
不要在inode接近耗尽时先运行大范围压缩、打包或扫描任务。这些操作本身可能需要创建临时文件,反而加重故障。
第四步:用文件系统信息解释异常差异
区分逻辑大小和实际分配空间
对候选文件可以同时查看逻辑大小和分配块数:
sudo find "$SITE_ROOT" -xdev -type f \
-printf '%s %b %p\n' 2>/dev/null |
sort -nr | head -n 30
GNU find中的%s是文件逻辑大小,%b是分配的512字节块数量。稀疏文件、预分配文件或文件系统特性可能使两者不同。不能用ls -lh看到的逻辑大小直接推断实际占用。
确认挂载、链接和隐藏目录
du统计时,符号链接、独立挂载点和绑定挂载可能改变结果。再次确认挂载关系:
findmnt
findmnt -T "$SITE_ROOT"
如果网站目录下挂载了独立文件系统,使用不带-x的du可能把该挂载点中的数据算进网站目录;使用带-x的du则会将其排除。两种结果都可能是正确的,关键在于统计目标是否明确。
如果发现文件系统被挂载为只读,或内核日志出现I/O错误,不应继续通过删除日志来“腾空间”。此时应先保留现场和备份重要数据,再评估底层存储或文件系统状态:
dmesg -T | egrep -i 'I/O error|filesystem|read-only|corrupt|ext4|xfs'
sudo journalctl -k -b | egrep -i 'I/O error|filesystem|read-only|corrupt'
命令输出受内核权限和发行版配置影响,可能为空或无法读取。文件系统检查工具不能在正在使用的根文件系统上直接运行;需要离线维护环境、完整备份和明确的回滚方案。不要在挂载状态不明时自行执行修复操作。
第五步:在异常时段采集I/O延迟
如果容量和inode都没有解释问题,再观察存储I/O。以下命令适用于已安装sysstat工具的Linux系统:
command -v iostat
sudo iostat -xz 1 5
如果系统没有iostat,先核对发行版和软件包来源,再决定是否安装,不要为了临时排查直接在生产高峰执行未经评估的变更。
主要指标可以这样理解:
r/s、w/s:每秒读写请求数量;rkB/s、wkB/s:每秒读写数据量;await:请求从提交到完成的平均等待时间,通常包含排队和设备处理时间;aqu-sz:平均等待队列长度;%util:设备处于处理请求状态的时间比例。
这些指标必须与设备类型、并发量、采样时段和历史基线一起解释,不能套用一个固定阈值。相同的await数值,在不同存储设备、不同请求大小和不同业务负载下,含义可能不同。
同时采集系统和进程层面的信息:
vmstat 1 5
command -v pidstat
sudo pidstat -d 1 5
判断关系时可以参考以下分支:
- 写入量、队列和
await同时升高:可能存在大量日志写入、缓存写入或其他同步写操作,需要继续对齐进程和文件增长时间; - 只有网站响应变慢,但设备I/O指标平稳:不能把原因归于磁盘,应回到应用、数据库或网络请求链路排查;
- 日志轮转或压缩时短时延迟升高:可能是轮转、压缩和业务写入集中发生,需要比较轮转前后的采样结果;
iowait升高但设备指标不明显:可能是采样范围、设备映射或进程等待类型不匹配,不能仅凭iowait判断磁盘故障;- 内核日志出现读写错误,同时I/O等待升高:优先按存储或文件系统故障处理,停止无关清理和高写入操作。
iostat采样的五个间隔只代表该命令运行期间的状态,不是全天性能结论。应分别在异常时段和相对正常时段采样,并记录服务器、文件系统、业务负载和具体时间。
用证据链而不是单个指标做判断
一次完整的定位至少应把下列信息放到同一时间线上:
| 证据 | 支持的判断 | 不能单独证明 |
|---|---|---|
df -hT持续升高 | 某个文件系统的块空间正在减少 | 一定是网站日志导致 |
df -ih接近满值 | inode资源可能成为限制 | 大文件一定很多 |
| 日志目录总量和文件大小增长 | 日志是空间增长候选来源 | 日志增长一定由真实访客造成 |
lsof +L1发现大文件 | 已删除文件仍被进程占用 | 该进程为什么没有释放文件 |
iostat中写入和等待同步升高 | 存在存储写入压力或排队 | 一定是底层设备损坏 |
| 内核日志出现I/O错误 | 需要排查设备或文件系统异常 | 仅靠删除文件即可恢复 |
推荐按低风险到高风险的顺序执行:
- 保存时间、主机名、挂载点、
df -hT和df -ih结果。 - 使用
du -x定位容量集中目录。 - 列出日志、缓存、上传和临时文件的大小及修改时间。
- 检查日志轮转模拟结果和系统日志占用。
- 检查已删除但仍被打开的文件。
- 在异常时段采集
iostat、vmstat和进程I/O。 - 只有确认增长来源后,才调整日志保留、缓存过期或文件清理策略。
- 涉及服务重启、日志删除或文件系统修复时,先备份并安排可回退窗口。
常见误判与处理边界
只看根目录的df
根文件系统满,不代表网站目录满。可能是系统日志、临时目录、备份文件或其他挂载点占用。必须根据findmnt确认实际挂载关系,再分别统计。
只删除最大的日志文件
如果日志轮转失效,删除活动日志可能导致应用继续写入已删除文件,空间并不会立即释放。应先确认进程打开的文件描述符,再使用应用支持的重新打开或平滑重载方式。
只看容量,不看inode
大量小文件是多语言缓存和临时文件中较常见的风险。容量尚未达到限制时,也要定期记录df -i,否则可能在部署或上传时突然失败。
看到I/O延迟就更换存储
await升高可能来自日志集中写入、同步写操作、轮转压缩、内存回收或其他进程竞争。只有在同一时间段内,I/O等待、设备队列、进程写入和内核错误形成一致证据时,才适合进一步评估底层存储问题。
清理后立即认为故障已解决
清理只改变当前占用,不代表增长机制已经消失。若没有设置日志轮转、缓存过期、临时文件回收或异常日志降噪,空间可能再次快速增长。
用复测决定容量和处置边界
完成日志策略或文件清理调整后,应在与原异常相近的业务负载下复测,而不是只看清理后的瞬时空间。至少重新记录:
date -Is
df -hT "$SITE_ROOT"
df -ih "$SITE_ROOT"
sudo du -xhd1 "$SITE_ROOT" 2>/dev/null | sort -h
sudo journalctl --disk-usage
如果问题与I/O有关,还要在相同时间窗口再次运行:
sudo iostat -xz 1 5
vmstat 1 5
sudo pidstat -d 1 5
复测应比较以下结果:
- 文件系统容量是否仍以相近速度增长;
- inode增长是否停止或明显放缓;
- 日志活动文件和轮转文件是否符合保留策略;
- 是否仍有已删除文件长期被打开;
- 异常时段的写入量和等待队列是否再次升高;
- 应用是否能够继续写日志、创建临时文件和完成部署任务。
当df、df -i、日志目录增长和I/O采样能够相互印证时,才能判断是容量规划问题、inode数量问题、日志策略问题,还是文件系统与存储层异常。若不同指标指向不同方向,应保留现场继续拆分挂载点、进程和时间段,而不是用单一阈值决定扩容或删除数据。