admin管理员组

文章数量:1608886

“no space left on device”(磁盘空间不足)问题

因为遇到了相关报错,在网上搜索一番,发现算是一个常见错误。
以下把几个值得参考的博文简单汇总一下,做个记录,以后好翻出来查看。

一、inode 和 block的概念
1.inode table (inode 表格)

iNode是用来存储数据属性信息的,iNode包含的属性包括:文件大小、属组、归属的用户组、读写权限、文件类型、修改时间、还包括指向文件实体的指针功能(iNode节点和block的对应关系),但是,iNode不包括文件名
ls -i,就可以看到inode节点了。
inode除了记录文件属性的信息外,还会为每个文件进行信息索引,所以就有了inode的数值,操作系统根据指令,即可通过inode的值最快的找到相对应的文件实体。inode是一串数字,不同的文件对应的inode在文件系统中是唯一的。inode相同的文件,互为硬链接文件(文件又一个入口)。一个文件被创建后至少要占用一个inode和一个block。如果一个文件很大,可能占多个block,如果文件很小,至少占一个,并且剩余空间不能被其他的文件使用。
因为inode要存放文件的属性信息,所以inode是有大小的,CentOS5 inode的默认大小为128字节,而CentOS6 inode的默认大小是256字节,inode的大小在文件系统被格式化之后就无法更改了,格式化前可以指定inode大小。
生成和指定iNode大小,mkfs.ext4 -b 2048 -I 256 /dev/sdb
查看iNode的总量和使用量命令:df -i

2.data block (资料区块)
Block 是用来存储实际数据的。
Block是记录文件内容的区域,inode则是记录该文件的属性及其放置在哪个Block之内的信息。
理解:可以把iNode理解为一本书的目录,block理解为书的每一页。
磁盘读取数据是按block为单位读取的。一个文件可能占用多个block。每读取一个block就会消耗一次磁盘I/O。如果要提升磁盘IO性能,那么就要尽可能一次性读取数据尽量的多。
一个block只能存放一个文件的内容,无论内容有多小。如果block 4K,那么存放1K的文件,剩余3K就浪费了。
block并非越大越好。block太大对于小文件存放就会浪费磁盘空间,例如:1000K的文件,block为4K,占用250个block,block为1K,占1000个block。文件较大时,block设置大一些会提升磁盘仿效效率。

3.小结
查看某分区的block和inode的数量,通常block比inode多
dumpe2fs /dev/sda2 |grep ‘Block count’
dumpe2fs /dev/sda2 |grep ‘Inode count’
dumpe2fs /dev/sda2 |grep ‘Block size’
dumpe2fs /dev/sda2 |grep ‘Inode size’

二、“no space left on device”(磁盘空间不足)问题
磁盘满了就分为,inode满了,和block满了,以及一种特殊的情况,下面我们来具体分析,以及对应的解决方案
1.查看是否是block满了
df -h --查看所有block使用情况
[root@test-os testuser]# du -sh /usr/* |grep G ###查找大文件
7.3G /usr/local
[root@test-os testuser]# du -sh /usr/local/ |grep G
7.3G /usr/local/bin
[root@test-os testuser]# du -sh /usr/local/bin/ |grep G
7.3G /usr/local/bin/1g
[root@test-os testuser]# \rm -f /usr/local/bin/1g ###删除大文件

使用du -h -x --max-depth=1 ,查看占用过高的目录,对过高目录中的内容适当删减。

2.查看是否inode满了(df -h发现还有空间)
[root@test-os logs]# touch {1…118}.txt
touch: cannot touch `118.txt’: No space left on device
[root@test-os logs]# df -i ###查看inode使用情况
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 593344 56998 536346 10% /
tmpfs 238282 1 238281 1% /dev/shm
/dev/sda1 51200 39 51161 1% /boot
/tmp/1m 128 128 0 100% /app/logs ###使用100%了
[root@test-os logs]# pwd
/app/logs
[root@test-os logs]# \rm -f .txt ###如果小文件太多,采用a.txt b*.txt 一批一批的删
[root@test-os logs]# df -i ###接着查看
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 593344 56998 536346 10% /
tmpfs 238282 1 238281 1% /dev/shm
/dev/sda1 51200 39 51161 1% /boot
/tmp/1m 128 11 117 9% /app/logs
###如果不知道小文件都在哪里怎么查找?
###查找系统中 目录大小大于1M(目录一般大小为4K,所以目录要是大了那么文件必然很多)
[root@localhost testuser]# find / -size +4k -type d |xargs ls -ldhi
11 drwx------ 2 root root 12K Sep 23 00:49 /boot/lost+found
946 drwxr-xr-x 12 root root 4.1K Sep 22 17:53 /dev
1114113 drwxr-xr-x 88 root root 12K Sep 22 19:55 /etc
262145 drwxr-xr-x 13 root root 12K Sep 22 18:59 /lib

3.查看是不是文件被占用一直没被彻底删除(特殊原因)
这种情况往往是容易被忽略,也是让人郁闷的,因为你会发现df -h明明已经有空间了,但是就是放不进去东西
[root@test-os ~]# lsof |grep deleted
rsyslogd 1250 root 1w REG 8,3 4888889358 140789 /var/log/messages (deleted)
[root@test-os ~]# #lsof 显示出系统中被打开的文件
[root@test-os ~]# #第一列 软件/服务的名称
[root@test-os ~]# #第八列 文件的大小
[root@test-os ~]# #第10列 文件的名字
[root@test-os ~]# #第11列 标记(硬链接数为0 进程调用数不为零 就会有 delete)
###重启对应的服务 释放磁盘空间
[root@test-os ~]# /etc/init.d/rsyslog restart
Shutting down system logger: [ OK ]
Starting system logger: [ OK ]
[root@test-os ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 8.8G 1.5G 6.9G 18% /
tmpfs 931M 0 931M 0% /dev/shm
/dev/sda1 190M 40M 141M 22% /boot
/tmp/1m 1003K 19K 933K 2% /app/logs

三、案例
1.在linux上使用crontab -e 编辑crontab时(crontab -l 可以查看),系统提示:No space left on device。
发现,/var/spool/postfix/maildrop 下面有很多文件,直接用rm -rf 删除会跳出root,可以使用# ls | xargs rm -f 来删除。
分析原因:系统中cron执行的程序有输出内容(异常),输出内容会以邮件形式发给cron的用户,而sendmail没有启动所以就产生了这些文件。
解决方法:可以执行 crontab -e,在最开头添加 MAILTO=’"’ 保存,然后 server crond restart 重启 crond;或者,将crontab里面的命令后面加上> /dev/null 2>&1

2.when you create a new directory or file , system will say : No space left on device
创建文件或者目录时,提示No space left on device。df -h 查看磁盘使用情况时发现磁盘容量还很大,但是使用df -i 发现inode已经耗尽。解决方法同上。

3.MySQL导入几十G数据后创建索引时提示空间不足(Errcode: 28 - No space left on device)
用ETL工具进行一系列数据入库操作,涉及到一些上几十G的大表的时候,总是会出现异常:Errcode: 28 - No space left on device。
查看了一下机器的磁盘使用情况,
还有200多G的磁盘空间,导入一张几十G的表,理论上是没什么问题的。很明显问题不是因为磁盘存储空间不足导致的。因为数据导入完成之后,还有一个创建索引的步骤。后面再分析了一下创建索引的过程 。
MySQL 在给一张表建索引的时候 ,会有一个复制数据到临时表的一个操作。再看了 一下MySQL的配置,没有指定临时空间,MySQL默认使用了根目录下面的空间作为临时 空间。
对比一下临时空间的大小以及导入的数据文件大小。
数据文件有41G之多,根目录下能作为临时空间的只有39G,明显是放不下的。

结果是清理了MySQL作为临时空间的挂载点(或者修改my.conf配置文件,指向另一个更大存储空间的挂载点,这个需要重启MySQL),这样数据就可以导入 后正常创建索引了。

本文标签: 磁盘空间Spaceleftdevice