文件刪除詳解
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裏面的時候,原始數據才會真正的消失。為什麽文件被刪除之後進程還能繼續使用呢?(可以想成,一個人在工廠裏面上班的時候別人是不去查你的個人信息的,不管你有沒有身份,你都能一直幹活,重啟服務就相當於工廠下班在上班,在上班的時候就要查你的個人信息了,如果你信息不存在,那麽你就沒辦法上班了。)
文件刪除詳解