近期有些网友想要了解CentOS移动正在写入的文件,lsof查看文件句柄是否释放的相关情况,小编通过整理给您分析,根据自身经验分享CentOS移动正在写入的文件,lsof查看文件句柄是否释放有关知识。
CentOS移动正在写入的文件,lsof查看文件句柄是否释放
凌晨两点,机房告警灯闪成一片红海,日志分区飙到99%。我拎着咖啡冲进去,第一眼就瞅见那个疯狂膨胀的app.log——半小时前才2 G,现在已经18 G,还在以每秒百兆的速度往上窜。磁盘快炸了,业务不能停,怎么办?直接mv?还是cp再rm?别急,先摸清文件到底被谁攥在手里,否则移动完空间也不释放,白忙活。
先别动文件,lsof一眼锁定“凶手”
lsof | grep app.log,回车瞬间输出一行关键信息:
java 18347 app 7u REG 253,3 19327352832 1048582 /opt/logs/app.log (deleted)
看到后面那个(deleted)没?进程18347还死死拽着旧inode,磁盘空间被标记“已删”却并未真正归还系统。此时就算你把文件挪到月球,空间也照占不误。句柄不释放,df -h永远红给你看。移动正在写入的文件,两套方案对比
方案A:直接mv,风险最高
mv /opt/logs/app.log /opt/logs/app.log.old,命令敲下去,ls已经看不到原文件,但lsof再扫,依旧显示(deleted)。磁盘空间纹丝不动,业务进程继续往旧inode写。等它自己滚动?可能天亮都滚不完。mv只改了目录项,没切断写入流,空间不会立刻降。
方案B:echo 0 > 截断,秒级释放
先cp /opt/logs/app.log /backup/app.log.$(date +%s)留底,再执行:
echo '' > /opt/logs/app.log
或更干脆:
truncate -s 0 /opt/logs/app.log
文件大小瞬间变0,lsof里SIZE列从18 G掉到0,df -h同步下降。截断操作把旧inode清成白纸,进程文件偏移量不变,却不再占空间,零停机、零日志丢失。
句柄到底放没放?lsof三招验证
lsof -p 18347 | grep log,看SIZE列是否归零;lsof +L1,专门列出已删除却仍被占用的文件,若结果为空,说明清理成功;awk '{print $2}' /proc/18347/fdinfo/7 | grep pos,查看当前写入偏移,若接近0,则进程已感知到截断。
三条命令交叉验证,确保句柄释放、空间回收、应用无感知。
真实现场:nginx访问日志滚动脚本
线上nginx每天生成上百G access.log,用logrotate偶尔延迟,运维干脆写了个60秒一次的cron:
#!/bin/bash
LOG=/var/log/nginx/access.log
cp $LOG $LOG.$(date +%s)
kill -USR1 $(cat /var/run/nginx.pid)
sleep 2
echo '' > $LOG
kill -USR1让nginx立刻重新打开文件描述符,旧文件句柄释放;接着echo截断,空间秒回。USR1信号+清空组合拳,比单纯mv可靠一万倍。
避坑指南:这些骚操作别踩
- ❌ rm后重启进程:高并发服务重启代价巨大,客户直接投诉。
- ❌ mv再建同名空文件:新文件inode不同,进程依旧写旧句柄,空间不释放。
- ❌ 依赖日志框架自滚动:logback、log4j2滚动策略触发前,磁盘早被撑爆。
最稳妥路径永远是:留底→通知进程重开句柄→截断原文件→lsof二次确认。
告警灯熄灭,咖啡还剩半杯。df -h从99%落到12%,业务曲线平滑无抖动。记住这句:在Linux世界,文件名字和磁盘空间是两回事,lsof才是真相照妖镜。下次再遇到疯狂日志,别急着mv,先让lsof告诉你句柄放没放。









