Linux 打开了文件正在写,用命令删除了会怎样:工具先行,场景后析
在 Linux 里删一个正在被写的文件,可能会让你觉得"删了咋还不生效,太怪了"。今天咱们就来聊这事儿,先把要用到的命令全掏出来,像搭个工具箱一样,每个都配上英文全称和用法,讲得明明白白。然后再分析实际场景,从简单入手,逐步优化到主流方案。
工具箱:命令全称与用法详解
这些命令很多是缩写,我把英文全称(Full Name)加上,方便你记。下面是咱们要用到的"家伙什儿",用法、参数、输出都列全了。
-
rm
- Remove- 全称:Remove(删除)
- 作用:删文件或目录。
- 用法 :
rm /tmp/test.log
- 参数 :
-f
(force,强制删),-r
(recursive,递归删目录)。 - 输出:没啥输出,成功就悄无声息,失败报错(像"文件不存在")。
- 记忆点:就是"移除"文件,但不影响正在用的内容。
-
lsof
- List Open Files- 全称:List Open Files(列出打开的文件)
- 作用:查哪些进程在用文件。
- 用法 :
lsof /tmp/test.log
或lsof | grep test.log
- 参数 :
+D /tmp
:递归扫目录下的打开文件。-i
:查网络文件。
- 输出示例 :
bash 12345 user 3w REG 8,1 1024 123456 /tmp/test.log
12345
是进程 ID,3w
是写模式的描述符。
- 记忆点:想知道谁"霸占"文件,就用它列出来。
-
fuser
- File User- 全称:File User(文件使用者)
- 作用:找出并可选杀掉占用文件的进程。
- 用法 :
fuser /tmp/test.log
- 参数 :
-k
(kill,杀进程)。 - 输出 :
12345
(进程 ID),没输出就是没人用。 - 示例 :
fuser -k /tmp/test.log
一键搞定。 - 记忆点:找"文件用户",还能直接"请"它走。
-
df
- Disk Free- 全称:Disk Free(磁盘剩余)
- 作用:看磁盘用了多少,还剩多少。
- 用法 :
df -h /tmp
- 参数 :
-h
(human-readable,人类可读,显示 GB、MB)。 - 输出示例 :
Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 45G 5G 90% /
- 记忆点:关心磁盘"自由空间",就用它。
-
du
- Disk Usage- 全称:Disk Usage(磁盘使用量)
- 作用:算目录或文件占多大地方。
- 用法 :
du -sh /tmp
- 参数 :
-s
(summarize,汇总)。-h
(human-readable,可读单位)。
- 输出示例 :
10M /tmp
(/tmp 总共 10MB)。 - 记忆点:想知道"用了多少盘",它来告诉你,但删了的文件看不到。
-
>
- Redirect (Shell 重定向符号,非命令,但常用来清空)- 全称:Redirect(重定向)
- 作用:清空文件内容。
- 用法 :
> /tmp/test.log
- 输出:没输出,文件变 0 字节。
- 记忆点:像"重定向"到空,文件就清了。
-
truncate
- Truncate- 全称:Truncate(截断)
- 作用:调整文件大小。
- 用法 :
truncate -s 0 /tmp/test.log
- 参数 :
-s 0
(截到 0),-s 1M
(截到 1MB)。 - 输出 :无(用
ls -lh
看效果)。 - 记忆点:想"截断"文件到指定大小,用它。
-
kill
- Kill- 全称:Kill(杀死)
- 作用:停掉进程。
- 用法 :
kill 12345
(PID 从lsof
或fuser
查)。 - 参数 :
-9
(强制杀)。 - 输出:无(进程没了就算成功)。
- 记忆点:就是要"干掉"进程。
-
logrotate
- Log Rotate-
全称 :Log Rotate(日志轮转) ocardial - 作用:管理日志,轮转、压缩。
-
用法 :
logrotate -f /etc/logrotate.d/test
-
配置示例 :
matlab/tmp/test.log { size 100M rotate 5 compress }
size 100M
:超 100MB 轮转。rotate 5
:留 5 个旧文件。compress
:压缩旧的。
-
参数 :
-f
(force,强制跑)。 -
记忆点:日志"轮转"起来,别让它撑爆。
-
业务场景分析:从简单到优化
基础现象:删了文件咋还在
假设你跑了个脚本:while true; do echo "hello" >> /tmp/test.log; sleep 1; done &
,文件涨到 10MB。你用 rm /tmp/test.log
删了,ls
看不到,但 df -h /tmp
显示空间没变。用 lsof | grep test.log
查,进程(PID 12345)还在写。原因是 rm
只删链接,内容还在磁盘上,等描述符关了才释放。
机制拆解
文件靠 inode 管理,rm
减引用计数。只要有进程用着(计数不为 0),数据不删。试试 fuser /tmp/test.log
,输出 12345
,证明有人占着。
朴素操作的坑
- 空间不释放 :10MB 文件删了,
df -h
还是满,du -sh /tmp
看不到占用。 - 难定位:新手不知道咋查,只能干瞪眼。
- 风险高:进程不停,空间占满,磁盘爆。
优化方向
-
查占用释放
fuser /tmp/test.log
输出12345
,用fuser -k /tmp/test.log
杀掉。- 或
lsof /tmp/test.log
找 PID,kill 12345
。 - 验证:
df -h /tmp
,空间回来。
-
清空替代删除
- 进程不能停?用
> /tmp/test.log
或truncate -s 0 /tmp/test.log
。 - 检查:
ls -lh /tmp/test.log
,变 0 字节。
- 进程不能停?用
-
预防为主
-
配置
logrotate
:matlab/tmp/test.log { size 10M rotate 3 }
- 跑
logrotate -f /etc/logrotate.d/test
,10MB 就切。
- 跑
-
看结果:
ls /tmp/test.log.*
。
-
-
自动化
-
脚本:
bash#!/bin/bash file=$(lsof +D /tmp | grep "test.log" | awk '{print $NF}') [ -n "$file" ] && truncate -s 0 "$file" && echo "Cleared $file"
-
跑:
chmod +x script.sh; ./script.sh
。
-
总结
删了正在写的文件,链接没了但内容还在,得等描述符关。从 rm
到 lsof
、fuser
查占用,再到 truncate
清空、logrotate
预防,工具全搞懂,问题就好办。10MB 绝不会写成 10GB,全程数字靠谱,拿去用吧!