第1章 创建文件的时候提示no space left to device的解决办法
1.1 inode被用完。
模拟环境:
[root@LornBlood ~]# dd if=/dev/zero of=/dev/test count=10 bs\=10M
10+0 records in
10+0 records out
104857600 bytes (105 MB) copied, 0.303514 s, 345 MB/s
[root@LornBlood ~]# mkfs.ext4 /dev/test
mke2fs 1.41.12 (17-May-2010)
/dev/test is not a block special device.
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
25688 inodes, 102400 blocks
5120 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
13 block groups
8192 blocks per group, 8192 fragments per group
1976 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 20 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
[root@LornBlood ~]# mount -o loop /dev/test /app/logs/
[root@LornBlood ~]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda3 ext4 19G 1.7G 17G 10% /
tmpfs tmpfs 2.5G 0 2.5G 0% /dev/shm
/dev/sda1 ext4 190M 66M 115M 37% /boot
/dev/sr0 iso9660 3.7G 3.7G 0 100% /mnt
/dev/test ext4 93M 1.6M 87M 2% /app/logs
[root@LornBlood ~]# cd /app/logs/
[root@LornBlood logs]# touch test_{1..100000}.txt
[root@LornBlood logs]# mkdir haha.txt
mkdir: cannot create directory `haha.txt': No space left on device
解决排查思路:
碰到这种情况第一时间想到df -Th查看一下磁盘的使用率
[root@LornBlood logs]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda3 ext4 19G 1.7G 17G 10% /
tmpfs tmpfs 2.5G 0 2.5G 0% /dev/shm
/dev/sda1 ext4 190M 66M 115M 37% /boot
/dev/sr0 iso9660 3.7G 3.7G 0 100% /mnt
/dev/test ext4 93M 2.4M 86M 3% /app/logs
发现磁盘使用率才3%,这肯定不是block被用完,因为df -Th查看的是block信息
然后就想到看看是不是inode号被占满。使用df -i
[root@LornBlood logs]# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 1250928 71345 1179583 6% /
tmpfs 653285 1 653284 1% /dev/shm
/dev/sda1 51200 44 51156 1% /boot
/dev/sr0 0 0 0 - /mnt
/dev/test 25688 25688 0 100% /app/logs
发现inode使用率已经达到100%了,所以肯定是小文件太多了,才导致这个问题的,于是乎开始想办法查找这些小文件存放在那个地方。于是想小文件过多,说明他的文件名肯定就多,文件名有存放在他的上级目录的block块里面,我们看看那个目录的block大不就说明它里面的文件多吗?我们可以通过find命令来按照大小查找目录,找到最大的那个目录。然后删除它里面的文件。
[root@LornBlood logs]# find / -type d -size +800k|xargs ls -hdl
drwxr-xr-x 3 root root 884K Jul 29 14:34 /app/logs
记录好这个目录的权限,把这个目录删除,并再把它创建出来
1.2 Block被占满
还在上面那个分区里面进行模拟环境。
[root@LornBlood logs]# seq 100000000000 >>test.txt #生成一个大文件,时间过长
[root@LornBlood logs]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda3 ext4 19G 1.7G 17G 10% /
tmpfs tmpfs 2.5G 0 2.5G 0% /dev/shm
/dev/sda1 ext4 190M 66M 115M 37% /boot
/dev/sr0 iso9660 3.7G 3.7G 0 100% /mnt
/dev/test ext4 93M 91M 0 100% /app/logs
[root@LornBlood logs]# mkdir test.dir
mkdir: cannot create directory `test.dir': No space left on device
通过du -sh统计根目录下面最大的文件,然后就这样逐级查找,找到最大的那个文件,然后看他的作用是什么,如果能删除就删除,不能删除就剪切到别的地方。
[root@LornBlood logs]# du -sh /*| sort -h
[root@LornBlood logs]# du -sh /app/*| sort -h
90M /app/logs
[root@LornBlood logs]# du -sh /app/log/*| sort -h
90M /app/logs/test.txt
[root@LornBlood logs]# rm -rf /app/logs/test.txt
1.3 inode和block都还有空间,但写数据就是提示磁盘空间不足。
这种原因可能是因为那个大文件还正在被那个进程占用着。
[root@LornBlood logs]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda3 ext4 19G 5.8G 12G 33% /
/dev/sda1 ext4 190M 66M 115M 37% /boot
/dev/sr0 iso9660 3.7G 3.7G 0 100% /mnt
按照上面排查block的方式,来找出这个大文件,这里不查找
[root@LornBlood logs]# rm -rf /var/log/messages
[root@LornBlood logs]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda3 ext4 19G 5.8G 12G 33% /
tmpfs tmpfs 2.5G 0 2.5G 0% /dev/shm
/dev/sda1 ext4 190M 66M 115M 37% /boot
/dev/sr0 iso9660 3.7G 3.7G 0 100% /mnt
/dev/test ext4 93M 2.4M 86M 3% /app/logs
发现把这个文件删除之后磁盘的使用大小还是没有变化,这是因为/var/log/messages这个文件被rsyslog程序在占用,如何知道呢,我们可以查看lsof标签为delete的文件,看看这个文件还在不在,如果在找到对应调用这个程序的进程。然后重新启动这个进程,即可
[root@LornBlood logs]# lsof | grep delete
bash 2259 root cwd DIR 8,3 0 130925 /root (deleted)
rsyslogd 22037 root 1w REG 8,3 4444445244 130895 /var/log/messages (deleted)
然后重启这个服务即可
[root@LornBlood logs]# /etc/init.d/rsyslog restart
Shutting down system logger: [ OK ]
Starting system logger: [ OK ]
[root@LornBlood logs]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda3 ext4 19G 1.7G 17G 10% /
tmpfs tmpfs 2.5G 0 2.5G 0% /dev/shm
/dev/sda1 ext4 190M 66M 115M 37% /boot
/dev/sr0 iso9660 3.7G 3.7G 0 100% /mnt
/dev/test ext4 93M 2.4M 86M 3% /app/logs
说明:为什么我们这里选择则从其服务,而不是直接杀死这个进程,因为这个文件一直在被这个程序调用,说明这个服务肯定依赖于这个文件,重启服务会重新生成这个文件,服务正常使用,但是直接结束进程并不会有这个效果。所以我们选择重启服务。
第2章 Linux下删除文件的原理
Linux下删除文件是一个既复制有好玩的,在这里简单的描述一下自己对文件删除过程的看法。 Linux删除一个文件或者目录是首先看当前用户对这个文件或目录的父目录有没有权限,因为目录名和文件名是存放在上级目录的block块里面的。删除文件和目录实际上就是操作父目录的block块的内容。
要想搞清楚Linux下文件的删除原理就要弄清楚Linux下文件存储的原理:
1)Linux系统是通过inode(索引节点号)来区分文件的,而不是根据文件名。 2)Linux存储数据分为两部分:inode(存放文件属性),block(存放数据的实际信息) 3)文件名是存放在他的父目录的block里面的。 4)inode和文件名的对应关系是存放在父目录的block里面的。
查找文件的过程:
按照绝对路径查找文件,就按照路径名称一级一级的在block里面查找文件名和inode的对应关系
按照相对路径查找文件,就在当前的目录的block块里面查找文件名和inode的对应关系
找到inode号之后,通过inode来确定相应的属性,根据属性判断能不能操作这个目录或文件。修改完成之后把现在的属性保存到inode块里面。
第3章 进入删除文件过程的正题:
1,先判断删除文件的上级目录是否具有权限,有的话查找inode和文件名的对应关系,通过文件名来确定inode信息(因为我们查找的时候是通过文件名查找的,如果通过inode来找,就是按照inode来找文件名)。 2,有权限我们就删除这个文件名(这个时候删除的知识文件的名字,他的inode和block并没有删除),等到有新的数据写入到这个block块里面的时候数据才是真正的丢失。 3)为什么删除文件要i_count和i_link都为0才是真正的删除呢? 举个例子:一个人(Block块)具有×××(inode号),和姓名(文件名);他现在在一个工厂上班(相当于在被进程调用)。我们删除文件就是删除了这个人的姓名和他的×××信息的对应关系。 但是这个人(block块)和×××(inode)还是存在的。只有等待执行“Linux的垃圾回收机制(有兴趣可以观看:https://blog.csdn.net/wangcong02345/article/details/51823150)” 或者从新有数据写到这个block里面的时候,原始数据才会真正的消失。为什么文件被删除之后进程还能继续使用呢?(可以想成,一个人在工厂里面上班的时候别人是不去查你的个人信息的,不管你有没有身份,你都能一直干活,重启服务就相当于工厂下班在上班,在上班的时候就要查你的个人信息了,如果你信息不存在,那么你就没办法上班了。)