关于“No space left on device的原因” – 穆芝火煜-无欲则刚 – 博客频道 – CSDN.NET

看到这个错误,第一个反应是磁盘空间满了;但df一看,每个分区的空间都还富余的很。从munin 的监控图表上看 Filesystem usage 也很平稳,但下面的 Inode usage 就有问题了,其中一个分区的 usage 已经到了100%。赶紧跑到服务器上df -i检查,果然是 Inode 耗尽。原来这个分区是用来扔各种日志和临时文件的,其中有某个程序产生的临时文件又小又多,又没有进行定时回滚,造成在磁盘空间耗尽之前文件系统的 Inode 就被用光了。

  Linux/Unix like OS 的文件系统中每个目录树中的节点并不是像 Windows 那样直接包含文件的具体信息,而只包含了文件名和 Inode number 。通过 Inode number 所找到对应于文件名的 Inode 节点中才真正记录了文件的大小/物理地址/所有者/访问权限/时间戳/被硬链接的次数等实际的metadata。因此你可以在 Linux 系统中通过硬链接( hard link ) 的方式给某个文件创建无数个位于不同目录下的文件名,而实际的文件数据只需要一份拷贝。

  但也正因为这种文件系统的结构,当你在 Linux 中进行 IO 操作的时候,需要的资源除了磁盘空间以外,还要有剩余的 Inode 才行。缺省情况下, Linux 在系统安装过程中按照1个 Inode 对应 2k 磁盘空间来计算每个分区的最大 Inode 数。一旦文件系统创建之后,每个分区可用 Inode 数就无法进行动态调整。

  正常来说,一般不太会出现某个分区的 Inode 耗尽而磁盘空间尚余的情况,除非像我碰到的这样垃圾小文件疯长而又没进行有效的清理。但如果确实需要的话,可以在创建文件系统(比如用mke2fs)的时候根据实际需要来调整这个参数(比如分区如果用于存放超大视频文件的话 Inode 的数量可以少一些;如果打算存放的文件是大量小于 2k 的迷你文件的话就要考虑多创建一些 Inode)。

No space left on device 原因:

  超出系统中同时运行的最大 message queue 个数限制 : 在root下用sysctl kernel.msgmni检查该参数,sysctl -w kernel.msgmni=XXX重新设定即可。

附录一则:“比较罕见的一个问题,磁盘文件数目太多导致的LISTENER监听起不来”解决方法:[转载]

问题提出:一台测试的服务器,停电再起来后发现listener起不来,报错如下:Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.191.100)(PORT=1521)))Error listening on: (ADDRESS=(PROTOCOL=ipc)(PARTIAL=yes)(QUEUESIZE=1))No longer listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.191.100)(PORT=1521)))TNS-12549: TNSperating system resource quota exceededTNS-12560: TNSrotocol adapter errorTNS-00519: Operating system resource quota exceededLinux Error: 28: No space left on device

 

首先查看log文件,已经2G了,打开看看日志里面也没发现什么异常,认为日志是自然增长到这么大的,于是直接cat /dev/null>listener.log把日志清空。然后listener还是起不来,仍然报上面的错误。之后重启机器,还是不行,检查磁盘空间:Oracle@test-db1admin]$ df -hFilesystem Size Used Avail Use% Mounted on/dev/sdb2 4.9G 1.9G 2.7G 42% //dev/sdb1 99M 15M 79M 16% /boot/dev/sdb7 1012M 493M 468M 52% /home/dev/sdb8 61G 41G 18G 71% /optnone 1000M 0 1000M 0% /dev/shm/dev/sdb5 2.0G 33M 1.9G 2% /tmp/dev/sdb6 1012M 606M 355M 64% /var/dev/sda1 34G 14G 19G 43% /oracle安装在/opt目录,上面还有18个G的空间,而且每个磁盘空间都很多。查看process限制,top发现系统才开了50个process,而对oracle的限制是2048个。在pub的发帖,地址如下:http://www.itpub.NET/showthread.PHP?s=&threadid=809058&perpage=10&pagenumber=1一直没有解决,后来通知同事有这个问题存在。周一上班,同事说这个问题已经被他解决了,并推荐一篇文章给我,地址如下:http://www.zeali.Net/entry/480摘录一部分:Linux/Unix like OS 的文件系统中每个目录树中的节点并不是像 Windows 那样直接包含文件的具体信息,而只包含了文件名和 Inode number 。通过 Inode number 所找到对应于文件名的 Inode 节点中才真正记录了文件的大小/物理地址/所有者/访问权限/时间戳/被硬链接的次数等实际的 metadata 。因此你可以在 Linux 系统中通过硬链接( hard link ) 的方式给某个文件创建无数个位于不同目录下的文件名,而实际的文件数据只需要一份拷贝。但也正因为这种文件系统的结构,当你在 Linux 中进行 IO 操作的时候,需要的资源除了磁盘空间以外,还要有剩余的 Inode 才行。缺省情况下, Linux 在系统安装过程中按照1个 Inode 对应 2k 磁盘空间来计算每个分区的最大 Inode 数。一旦文件系统创建之后,每个分区可用 Inode 数就无法进行动态调整。正常来说,一般不太会出现某个分区的 Inode 耗尽而磁盘空间尚余的情况,除非像我碰到的这样垃圾小文件疯长而又没进行有效的清理。但如果确实需要的话,可以在创建文件系统(比如用 mke2fs )的时候根据实际需要来调整这个参数(比如分区如果用于存放超大视频文件的话 Inode 的数量可以少一些;如果打算存放的文件是大量小于 2k 的迷你文件的话就要考虑多创建一些 Inode)。使用df -i命令可以看到每个分区的总inode数目和被使用的以及空闲的inode数目:[root@test-db1 log]# df -iFilesystem Inodes IUsed IFree IUse% Mounted on/dev/sdb2 640000 115018 524982 18% //dev/sdb1 26104 40 26064 1% /boot/dev/sdb7 131616 409 131207 1% /home/dev/sdb8 8077312 168316 7908996 3% /optnone 255900 1 255899 1% /dev/shm/dev/sdb5 262144 182 261962 1% /tmp/dev/sdb6 131616 1500 130116 2% /var/dev/sda1 4447744 117 4447627 1% /u01上面的结果是同事已经处理后的结果,原因是/var的一个子目录下产生很多很小的文件,删除后恢复正常,listener可以正常起来了。继续做下面一个试验:首先找到一个大小为200多k的测试文件[root@localhost test]# lltotal 208-rw-r--r-- 1 root root 206305 Mar 8 10:28 test.log然后查看/usr的inode使用情况[root@localhost test]# df -iFilesystem Inodes IUsed IFree IUse% Mounted on/dev/sda6 525888 98096 427792 19% /usr然后把test.log分割成每个字节一个文件,split的使用方法可以参考:http://zhang41082.itpub.net/post/7167/289531[root@localhost test]# split -a 10 -b 1 test.log统计分割后的总文件数目,比test.log的文件大小206305多了两个,这个一个是因为test.log文件本身占一个,还有就是统计的返回结果占一行,所以看到文件被成功分割为206305个。[root@localhost test]# ll | wc -l206307查看inode使用情况[root@localhost test]# df -iFilesystem Inodes IUsed IFree IUse% Mounted on/dev/sda6 525888 304401 221487 58% /usr可以看到,inode增加了304401-98096=206305个。然后把test.log重命名为test1.log,重新分裂[root@localhost test]# split -a 10 -b 1 test1.log z[root@localhost test]# ll|wc -l412612[root@localhost test]# df -iFilesystem Inodes IUsed IFree IUse% Mounted on/dev/sda6 525888 510706 15182 98% /usrinode已经使用了98%了,再重复一次[root@localhost test]# mv test1.log test2.log[root@localhost test]# split -a 10 -b 1 test2.log ysplit: yaaaaaaawly: No space left on device可以看到,进行到一半的时候已经不能对文件再进行分割了,而错误提示也已经出现 No space left on device。

总结:这类错误是比较少见的错误,有时候oracle的bug或者其他原因会导致某个目录的trace文件数目疯长,这时候就要小心这个问题了,因此日常的系统监控除了要监控磁盘空间的大小,对inode的使用情况也应该进行监控。从这个问题可以看出,操作系统的知识多么重要,感谢zeal的文章,感谢同事提供了这篇文章。

 

后续和补充:

今天看到pub上eygle给出了更合理的解释,放在这里作为补充。

为什么/var目录的inode满了会影响到装在/opt目录的oracle不能启动呢?原来listener启动的时候会在/var/tmp目录下的.oracle隐藏目录下创建两个临时文件:

[oracle@stream .oracle]$ lltotal 0srwxrwxrwx 1 oracle oinstall 0 Feb 5 05:49 s#4036.1srwxrwxrwx 1 oracle oinstall 0 Feb 5 05:49 s#4036.2srwxrwxrwx 1 oracle oinstall 0 Apr 20 04:26 s#5332.1srwxrwxrwx 1 oracle oinstall 0 Apr 20 04:26 s#5332.2srwxrwxrwx 1 oracle oinstall 0 Jan 22 21:53 s#7306.1srwxrwxrwx 1 oracle oinstall 0 Jan 22 21:53 s#7306.2srwxrwxrwx 1 oracle oinstall 0 Jan 13 04:21 s#9611.1srwxrwxrwx 1 oracle oinstall 0 Jan 13 04:21 s#9611.2

可以看到这个临时文件确实是成对出现的。

最新回复

 

EYGLE的trace文件中很明显,execve("/opt/oracle/product/9.2.0/bin/lsnrctl", ["lsnrctl", "start"], [/* 33 vars */]) = 0connect(4, {sa_family=AF_UNIX, path="/var/run/.nscd_socket"}, 110) = -1 ENOENT (No such file or directory)access("/var/tmp/.oracle", F_OK) = 0access("/var/tmp/.oracle/sEXTPROC", F_OK) = 0connect(4, {sa_family=AF_UNIX, path="/var/tmp/.oracle/sEXTPROC"}, 110) = 0如果文件创建不了,导致不能继续执行下面的操作了,猜测,当时如果用strace做跟踪,你的access("/var/tmp/.oracle", F_OK) = 0状态可能不是0了(0可能代表的是两个临时文件创建成功),呵呵!

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: