过多的内存文件/dev/shm导致死机
我们的IPS是基于Linux系统的一款设备,最近总是频繁死机,死机之后即不能从终端登陆,也不能连接屏幕查看打印信息。万般无赖之下,我只能在没有死机的情况下使用top命令,然后一直盯着终端,看看在死机之前有没有什么异常现象。通过半天的观察,我终于发现了一些异常之处,当系统变得越来越缓慢的时候,系统内存处于比较低的状态,而另一个叫cached的参数却很高,后来我了解到,cached所指的空间一般是为文件操作所分配的空间,也就是文件缓存,例如当文件打开之后,向文件中写入数据,这些数据都会先保存在内存中,直到这些数据被写入磁盘,才会释放这一部分内存空间,而cached所指的值即为这部分空间的大小,也就是说这部分空间是被占用的,不能被使用的。下图中标记了free和cached的空间大小:
在网上搜了一下,发现这一部分空间也不是完全不能使用,可以通过一个方法将缓冲区中的数据写到磁盘文件中,从而释放缓冲区所占用的空间,具体介绍如下:
复制代码 代码如下:
echo 3 > /proc/sys/vm/drop_caches
说明:
1>. /proc是一个虚拟文件系统,我们可以通过对它的读写操作作为与kernel实体间进行通信的一种手段。也就是说可以通过修改/proc中的文件,来对当前kernel的行为做出调整。也就是说我们可以通过调整/proc/sys/vm/drop_caches来释放内存。
2>. 关于drop_caches的官方说明如下:
复制代码 代码如下:
Writing to this file causes the kernel to drop clean caches,dentries and inodes from memory, causing that memory to becomefree.
To free pagecache, use echo 1 > /proc/sys/vm/drop_caches;
to free dentries and inodes, use echo 2 > /proc/sys/vm/drop_caches;
to free pagecache, dentries and inodes, use echo 3 >/proc/sys/vm/drop_caches.
Because this is a non-destructive operation and dirty objects are not freeable, the user should run sync first
但是我执行了sync和echo 3 >/proc/sys/vm/drop_caches 之后,cached的数值有所减少,但变化不大,因此死机的问题肯定不在这。
后来我想可能是某些进程打开的文件太多,导致这部分空间一直不能释放,于是我使用lsof命令查看了打开的文件描述符,里面确实有一些进程打开的文件特别多,多的高达好几百个。因此我猜测可能是这个原因导致内存消耗太多。因此我把那些打开太多文件的进程杀掉,这时候出现的状况是,free的值有所提高,但是cached的值变化仍然不大。因为进程被杀掉,进程所分配的内存空间被释放,所以free的值会增加,但是cached的值不变,所以占用cached的值过高并不是进程打开较多的文件导致的。
我又陷入了迷茫。。。
后来我在重启我杀掉的进程时竟然奇迹般地发现cached的值降了一半。通过查看了那个进程程序的源代码之后我终于发现,原来进程在刚启动的时候会删除/dev/shm目录下的文件,这才终于找到了问题的症结。因为/dev/shm/目录是Linux下默认的内存文件,这些文件虽然看似保存在磁盘中,其实是常驻在内存中的。使用df命令可以查看:
一般大小为物理内存的一半。因此将需要频繁读写的文件放在这可以有效提升执行效率。这里面的文件在系统重启后会丢失。虽然会提升效率但是有一个弊端就是,如果文件过多的话,就会大量地占用内存,导致系统内存耗尽,当系统内存不足时内核会根据进程的运行时间,占用内存情况以及权重等信息杀掉进程,如果杀掉的进程是核心进程,就会导致死机。具体可以查看Linux的OOM机制。
了解到大致的方向后,我在/dev/shm下使用ls –lh 命令,发现文件占用的空间也就几百K,与cached值的减小量并不一致,cached减小了接近500M,但是当我用du –h命令查看后才知道原来确实是占用了500M的空间,只不过ls只显示文件的大小,而du 则显示的是磁盘使用情况,因为磁盘是按照block分配的,即使文件只占用了一个字节,占用的磁盘空间仍然是1个block的大小。因此,如果目录中有大量地小文件就会导致这种情况。
使用命令tune2fs -l /dev/sda3 可以查看block的大小。
至此,系统死机的问题终于找到了,就是/dev/shm/下小文件过多而没有进行及时处理。