这类问题我又碰上了一次。CentOS 7.9 的站点允许传一百 M 的素材,客户一次性拖了二十个文件,nginx 报 500,错误日志写 client intended to send too large body 之后又出现 writev() failed,df 显示根分区满了。
第一反应是「上传中断后临时文件不会被清理,越积越多」,验证下来不成立。
排查方向其实有限,先把可能性排一排。client_body_buffer_size 很小,请求体被写成临时文件堆在 client_body_temp 里;client_body_temp_path 放在了根分区,没跟着数据盘走;同时上传的并发太高,临时文件在极短时间内把剩余空间吃光。
第一件事是看临时目录占了多大
du -sh /var/lib/nginx/body 2>/dev/null || du -sh /var/cache/nginx/client_temp
再往下把临时目录挪到数据盘
mkdir -p /data/nginx/body && chown nginx:nginx /data/nginx/body
接着配置里指过去并调大缓冲区
printf 'client_body_temp_path /data/nginx/body;\nclient_body_buffer_size 1m;\n' > /etc/nginx/conf.d/upload.conf
末了清掉残留的临时文件再重载
find /data/nginx/body -type f -mmin +60 -delete && nginx -t && nginx -s reload
恢复的判定其实很直接。再次上传二十个文件全部成功,client_temp 目录在数据盘上增长,根分区占用回到正常水位,错误日志不再有 writev 失败。
临时目录必须在 http 段配置,写在 server 里不生效;上传完成后 nginx 会自动删临时文件,但进程被杀时会留下残留,清理要按修改时间做。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
