1. 程式人生 > >文件刪除詳解

文件刪除詳解

strip 文件刪除 creating 查看 inux use 對應關系 root pro

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

文件刪除詳解