linux中删除文件后空间未释放

前言

最近项目上发现一个问题,有个服务的日志占用非常大,导致磁盘被占满后,服务异常,找到该日志后,直接一顿rm,发现日志非常被删除了,但是占用空间并没有释放

解决

经过查询得知,如果这个文件被某个进程占用的话,rm这个文件后,**会从文件系统的目录结构上解除链接(unlink)**,但是空间并不会被释放,需要停止这个进程后才会释放

扩展

有时候你可能并不知道这个删除的这个log或者文件是被谁占用了,可以使用以下命令查询文件被删除,但空间未释放的进程

1
lsof | grep deleted

输出的第一列一是进程名称,比如java服务就是java,第二列就是进程PID,最后一列就是被删除但是还被占用的文件,这是关键的几列

根据pid找到进程

1
ps -p 1234 -f
  • -p参数后跟的是进程号;
  • -f参数表示“完整格式”,会显示更详细的进程信息。

以上命令在执行后,将显示如下的信息:

UID PID PPID C STIME TTY TIME CMD
user 1234 5678 0 09:08 pts/0 00:00:00 some-command

其他

有时我想要查看某个进程信息,命令如下

1
ps -ef | grep tomcat

执行后会发现总有一个不相关的命令,就是执行该命令的进程,如果我们只是控制台这样用的话无所谓,因为你看得出来是不是,但是如果在脚本里这么写的话就会有问题,比如我之前写的一个脚本(目录下又很多jar服务,我想批量检查这个服务是否都在运行,其中关键的命令就是上面根据服务名找进程是否存在,如果直接用上面的命令的话,你会发现随便一个都能输出在运行,后台经过打印日志发现,它查询出来的其实是运行脚本命令的那个进程,因为那个命令里也包含了关键字

所以使用以下命令优化

1
ps -ef | grep 'xxx' | grep -v grep

grep -v grep:从之前的结果中再次筛选,排除包含 “grep” 的行,这样就只剩下了与 “xxx” 匹配的进程行。

当然-v后面可以是关键字,也可以是进程pid,所以如果在脚本中运行的话,需要这么写

1
2
3
4
# 获取脚本自身的进程ID(PID)
SCRIPT_PID=$$
# 排除自身的进程
ps -ef | grep "$NAME" | grep -v grep | grep -v "$SCRIPT_PID"