服务器运行一段时间后df查看磁盘剩余空间不足,通过du统计发现被几个文件占用,遂删除之。过了一段时间磁盘空间再次不足,通过du统计却找不到那么多大文件。搜索后才得知原因:文件删除后空间没有释放,du统计不到这部分文件;需要通过lsof排查,然后kill文件进程。以下记录排查处理过程:
df查看分区使用情况
df(Disk Free) 以磁盘分区为单位查看文件系统,获取硬盘被占用空间和剩余空间等信息。df 默认显示的文件大小单位Byte;使用命令df -h
,以KB,MB,GB为单位,提高可读性。
// 查看磁盘空间 (h--human-readable)
➜ df -h
// 统计结果
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 30G 7.9G 79% /
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 64K 1.9G 1% /dev/shm
tmpfs 1.9G 188M 1.7G 10% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
tmpfs 380M 0 380M 0% /run/user/0
/dev/vdc1 99G 4.1G 90G 5% /mnt
显示内容参数说明:
- Filesystem:文件系统
- Size: 分区大小
- Used: 已使用容量
- Avail: 还可以使用的容量
- Use%: 已用百分比
- Mounted on: 挂载点
du查看目录占用空间
du(Disk Usage) 含义为显示磁盘空间的使用情况,用于查看当前目录的总大小。
// 查看根目录下全部子目录大小
➜ du -h --max-depth=1 /
// 统计结果
106M /
0 /proc
1.1G /home
188M /run
93M /boot
5.6G /usr
4.0K /srv
35M /etc
478M /opt
0 /dev
2.2G /root
16K /lost-found
998 /var
4.0K /media
0 /sys
4.3G /mnt
15G /
df统计出根目录占用30G,而du统计结果为11G(排除/mnt占用),大约19G的空间去哪儿了呢?
搜索 linux du df空间不一致
才得知原因:当有其他进程打开某文件时文件被删除,就会将该文件标记为deleted(类似windows下的回收站状态),并删除其目录节点。使用du查看时,因为没有该删除状态文件的节点信息,所以就不做统计,从而导致与df的结果不一致。
使用lsof命令排查
在linux环境下,一切皆文件。lsof(LiSt Open Files)是一个查看当前系统文件的工具。
linux里的文件被删除后,空间没有被释放是因为在Linux系统中,通过rm或者文件管理器删除文件将会从文件系统的目录结构上解除链接(unlink)。然而如果文件是被打开的(有一个进程正在使用),那么进程将仍然可以读取该文件,磁盘空间也一直被占用。
通过命令 lsof |grep deleted
可以查看到状态为deleted的文件,如下:
// 查看状态为deleted的文件
➜ lsof |grep deleted
// 查看结果
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
dbus-daem 456 dbus txt REG 253,1 441144 141672 /usr/bin/dbus-daemon (deleted)
...
node 11595 11733 root txt REG 253,1 29851602 1461079 /home/elk/kibana-5.5.1-linux-x86_64/node/bin/node (deleted)
node 11595 11733 root 1w REG 253,1 11374904415 1059873 /home/elk/kibana-5.5.1-linux-x86_64/nohup.out (deleted)
node 11595 11733 root 2w REG 253,1 11374904415 1059873 /home/elk/kibana-5.5.1-linux-x86_64/nohup.out (deleted)
async_17 24113 24210 rabbitmq 1w REG 253,1 8556707104 659069 /var/log/rabbitmq/startup_log (deleted)
async_18 24113 24211 rabbitmq 1w REG 253,1 8556707104 659069 /var/log/rabbitmq/startup_log (deleted)
async_19 24113 24212 rabbitmq 1w REG 253,1 8556707104 659069 /var/log/rabbitmq/startup_log (deleted)
async_20 24113 24213 rabbitmq 1w REG 253,1 8556707104 659069 /var/log/rabbitmq/startup_log (deleted)
...
lsof输出各列信息的意义如下:
- COMMAND:进程的名称
- PID:进程标识符
- USER:进程所有者
- FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等 TYPE:文件类型,如DIR、REG等
- DEVICE:指定磁盘的名称
- SIZE:文件的大小(
单位Byte
) - NODE:索引节点(文件在磁盘上的标识)
- NAME:打开文件的名称
释放文件进程
释放文件的方法主要有两种:
- kill掉相应的进程(根据PID直接kill进程)
- 停掉使用这个文件的应用,让os自己主动回收磁盘空间
我这个环境已经不需要这些文件,所以直接停掉进程,生产环境中要谨慎排查。再次查看空间,文件已释放:
// 查看磁盘空间
➜ df -h
// 统计结果
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 11G 27G 29% /
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 64K 1.9G 1% /dev/shm
tmpfs 1.9G 188M 1.7G 10% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
tmpfs 380M 0 380M 0% /run/user/0
/dev/vdc1 99G 4.1G 90G 5% /mnt
Tips:
当linux打开一个文件的时候,Linux内核会为每个进程在/proc/ 『/proc/nnnn/fd/文件夹(nnnn为pid)』建立一个以其PID为名的文件夹用来保存进程的相关信息,而其子文件夹fd保存的是该进程打开的全部文件的FD(File Descriptor)。
这是一项高级技术,仅到管理员确定不会对执行中的进程造成影响时使用。应用程序对这样的方式支持的并不好,当一个正在使用的文件被截断可能会引发不可预知的问题