linux硬盘占用不正常

如题所述

第1个回答  2020-10-25
linux硬盘占用不正常?Copyright © 1999-2020, CSDN.NET, All Rights Reserved


 登录

JasonLiu1919
关注
linux磁盘异常占用 原创
2017-04-08 12:03:13

JasonLiu1919  

码龄9年

关注
背景:
某服务器报警,/根目录下磁盘超设定阈值。

分析:
1:查看磁盘占用情况
df -h
可以看出根目录已经占用了86%:

从上述信息可以看出根目录的文件系统对应的设备是/dev/sda2。

注:disk free(df,检查文件系统磁盘使用情况)
2:根目录的挂载情况
运行du -h -x --max-depth=1
查看是哪个目录占用的这么多空间,这个命令中的-x参数会让du命令不统计不在同一个磁盘分区上目录,或换句话说,忽略其他的磁盘挂载点。结果出乎意料,根本没有没有df中显示的8G那么多。


du的英文原义为“disk usage”,含义为显示磁盘空间的使用情况,统计目录(或文件)所占磁盘空间的大小。该命令的功能是逐级进入指定目录的每一个子目录并显示该目录占用文件系统数据块(1024字节)的情况。
du是以文件名、目录名为依据计算空间使用的,而df是以硬盘块使用情况来计算空间使用的。
当一个应用程序正在写一个大文件的时候,比如rm或者mv了这个文件,应用程序会占有句柄,并根据句柄所指磁盘位置直接写磁盘,而不会检查该文件是否被删除。

3:猜测:是否是因为有些进程使用已经被删除的文件?
当进程打开了某个文件时,只要该进程保持打开该文件,即使将其删除,它依然存在于磁盘中。这意味着,进程并不知道文件已经被删除,它仍然可以向打开该文件时提供给它的文件描述符进行读取和写入。除了该进程之外,这个文件是不可见的,因为已经删除了其相应的目录条目。
为此采用lsof(“list open files”)命令检查打开的文件,进而定位相应的进程。
lsof的命令结果:
Command、PID 和 User 列分别表示进程的名称、进程标识符 (PID) 和所有者名称。Device、SIZE/OFF、Node 和 Name 列涉及到文件本身的信息,分别表示指定磁盘的名称、文件的大小、索引节点(文件在磁盘上的标识)和该文件的确切名称。
lsof | grep '8,2' | grep 'deleted'
从执行结果发现有异常进程,其使用的文件已经被删除,但是该进程仍然持有该文件。
从下图可以看出父进程11864和子进程共用201508——26746.txt这个文件,但是该文件已经在物理磁盘中被删除。

通过cd /proc/11864进入该进程的系统位置信息:


4:查看父进程:

由此可以确定该进程启动的脚本位置信息,从而确定该进程的具体任务信息。
对该进程进行kill操作,再次查看文件系统的磁盘的使用情况:

从上述可以知,根目录的磁盘占用已经降到30%。从而确证是该进程所引起的根目录磁盘占用问题。

5:总结
一个文件创建,就新生成了一个inode节点,且inode节点的引用计数为1。当文件被一个进程打开,则在内存中缓冲建立此inode节点缓存,且其引用计数加1。一个文件可以被多次打开,创建多个文件描述符,但对应的inode节点只有一个,对应的磁盘存储只有一个,只是引用计数每打开一次加1。

当文件被rm,在操作系统内部其实是调用了unlink操作,其目录项被删除(du统计时就会忽略),如果其对应的inode节点的引用计数为0,则删除对应的inode节点和清除inode节点位图中对应的位,其对应磁盘可被再申请;但如果此文件被其他进程打开,则其对应的inode节点的引用计数不为0,则不会删除对应的inode节点和清除inode节点位图中对应的位,其对应磁盘不能被再申请,也就是在lsof下可以看到deleted句柄;当前文件被所有使用进程close后,系统删除对应的inode节点和清除inode节点位图中对应的位,其对应磁盘可被再申请。

一个被进程打开的文件被rm后,其目录项被删除了,在du命令下是不能被统计到,而其inode没有被删除,在df命令下是可以被统计到的,这就是在du和df存在较大差别的原因。

联合lsof和proc目录恢复删除的文件:
/proc 是一个目录,其中包含了反映内核和进程树的各种文件。这些文件和目录并不存在于磁盘中,因此当您对这些文件进行读取和写入时,实际上是在从操作系统本身获取相关信息。大多数与 lsof 相关的信息都存储于以进程的 PID 命名的目录中,所以 /proc/1234 中包含的是 PID 为 1234 的进程的信息。
在 /proc 目录的每个进程目录中存在着各种文件,它们可以使得应用程序简单地了解进程的内存空间、文件描述符列表、指向磁盘上的文件的符号链接和其他系统信息。lsof 实用程序使用该信息和其他关于内核内部状态的信息来产生其输出。所以如果一个进程使用的文件被删除了,
通过在该进程的目录中进行查找,此时可以访问进程的文件描述符。
向 lsof 传递文件名时,比如在 lsof /file/I/deleted 中,它首先使用 stat() 系统调用获得有关该文件的信息,不幸的是,这个文件已经被删除。在不同的操作系统中,lsof 可能可以从核心内存中捕获该文件的名称。

# lsof | grep error_log
输出结果:

httpd 2452 root 2w REG 33,2 499 3090660
/var/log/httpd/error_log (deleted)
httpd 2452 root 7w REG 33,2 499 3090660
/var/log/httpd/error_log (deleted)
... more httpd processes ...
1
2
3
4
5
1
2
3
4
5
在这个示例中,可以看到 PID 2452 打开文件的文件描述符为 2(标准错误)和 7。因此,可以在 /proc/2452/fd/7 中查看相应的信息,即可查找删除的文件:

cat /proc/2452/fd/7
[Sun Apr 30 04:02:48 2006] [notice] Digest: generating secret for digest authentication
[Sun Apr 30 04:02:48 2006] [notice] Digest: done
[Sun Apr 30 04:02:48 2006] [notice] LDAP: Built with OpenLDAP LDAP SDK
1
2
3
4
1
2
3
4
Linux 的优点在于,它保存了文件的名称,甚至可以告诉我们它已经被删除。在遭到破坏的系统中查找相关内容时,这是非常有用的内容,因为攻击者通常会删除日志以隐藏他们的踪迹。
从上述结果,我们知道 httpd 守护进程使用了 error_log 文件,所以可以使用 ps 命令找到这个 PID,然后可以查看这个守护进程打开的所有文件。
相似回答