天天看點

檔案系統深度了解之inode解讀

一、問題:

  在一台Linux伺服器的/data分區内建立檔案時,系統提示磁盤空間不足,用df -h指令檢視了一下磁盤使用情況,發現/data分區隻使用了66%,還有12G的剩餘空間。

  

二、分析問題:

  用df -i檢視了一下/data分區的索引節點(inode),發現已經用滿(IUsed=100%),導緻系統無法建立新目錄和檔案。inode譯成中文就是索引節點,每個儲存設備(例如硬碟)或儲存設備的分區被格式化為檔案系統後,應該有兩部份,一部份是inode,另一部份是Block,Block是用來存儲資料用的。而inode呢,就是用來存儲這些資料的資訊,這些資訊包括檔案大小、屬主、歸屬的使用者組、讀寫權限等。inode為每個檔案進行資訊索引,是以就有了inode的數值。作業系統根據指令,能通過inode值最快的找到相對應的檔案。

  而這台伺服器的Block雖然還有剩餘,但inode已經用滿,是以在建立新目錄或檔案時,系統提示磁盤空間不足。

  

 

檔案系統深度了解之inode解讀

三、原因:

  /data/cache目錄中存在數量非常多的小位元組緩存檔案,占用的Block不多,但是占用了大量的inode。

  

四、解決方案:

  1、删除/data/cache目錄中的部分檔案,釋放出/data分區的一部分inode。

  2、用軟連接配接将空閑分區/opt中的newcache目錄連接配接到/data/cache,使用/opt分區的inode來緩解/data分區inode不足的問題:

  ln -s /opt/newcache /data/cache

  3、增加空間

一、inode

硬碟的最小存儲機關叫做”扇區”(Sector)。每個扇區儲存512位元組(相當于0.5KB)。作業系統讀取硬碟的時候,不會一個個扇區地讀取,這樣效率太低,而是一次性讀取一個”塊”(block),每個”塊”(block)由八個連續的sector組成。這種由多個扇區組成的”塊”,是檔案存取的最小機關。”塊”的大小,最常見的是4KB,檔案資料都儲存在”塊”中,那麼還必須找到一個地方儲存檔案的元資訊,比如檔案的建立者、檔案的建立日期、檔案的大小等等。這種儲存檔案元資訊的區域就叫做inode,中文譯名為”索引節點”。每一個檔案都有對應的inode,裡面包含了與該檔案有關的一些資訊。

二、inode的内容

inode包含檔案的元資訊,具體有以下内容:

  * 檔案的位元組數

  * 檔案擁有者的User ID

  * 檔案的Group ID

  * 檔案的讀、寫、執行權限

  * 檔案的時間戳,共有三個:ctime指inode上一次變動的時間,mtime指檔案内容上一次變動的時間,atime指檔案上一次打開的時間。

  * 連結數,即有多少檔案名指向這個inode

  * 檔案資料block的位置

可以用stat指令檢視某個檔案的inode資訊:

[[email protected]_server home]# stat zabbix/
  File: `zabbix/'
  Size:        Blocks:           IO Block:    directory
Device: h/d Inode:       Links: 
Access: (/drwx------)  Uid: (  500/  zabbix)   Gid: (  500/  zabbix)
Access: -- :: +
Modify: -- :: +
Change: -- :: +
           

除了檔案名以外的所有檔案資訊,都存在inode之中。(為什麼沒有檔案名,繼續看下文)

三、inode的大小

概念:

inode也會消耗硬碟空間,是以硬碟格式化的時候,作業系統自動将硬碟分成兩個區域。一個是資料區,存放檔案資料;另一個是inode區(inode table),存放inode所包含的資訊。

每個inode節點的大小,一般是128位元組或256位元組。inode節點的總數,在格式化時就給定,一般是每1KB或每2KB就設定一個inode。假定在一塊1GB的硬碟中,每個inode節點的大小為128位元組,每1KB就設定一個inode,那麼inode table的大小就會達到128MB,占整塊硬碟的12.8%。

使用df -i可以檢視每個硬碟分區的inode總數和已經使用的數量

[root@Zabbix_server ~]# df -i
Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/sda3      1166880 103467 1063413    9% /
tmpfs                       % /dev/shm
/dev/sda1                    % /boot
/dev/sr0                               - /media/RHEL_6 i386 Disc 
[root@Zabbix_server ~]#
           

檢視每個inod

[root@Zabbix_server ~]# dumpe2fs /dev/sda3 | grep -i "inode size"
dumpe2fs  (-May-)
Inode size:              
           

預設未加入PATH中,需要手動加入

[[email protected]_server ~]# export PATH=/sbin/dumpe2fs:$PATH
[[email protected]_server ~]# echo $PATH
/sbin/dumpe2fs:/home/script:/usr/lib/qt-/bin:/usr/local/sbin:/usr/local/bin:/bin:/usr/sbin:/usr/bin:/home:/root/bin
[[email protected]_server ~]#
           

由于每個檔案都必須有一個inode,是以有可能發生inode已經用光,但是硬碟還未存滿的情況。這時,就無法在硬碟上建立新檔案,出現上面的執行個體情形。

inode大小調整:

一般來講,一個檔案将占用1~2個inode值。如果磁盤中主要為小檔案,可以适當的增加inode值。 如果大檔案居多,可以适量減少inode空間,可以使用 mkfs來調整inode數值。

具體方法&案例

[root@localhost ~]# df -i /dev/sdb5
Filesystem     Inodes IUsed  IFree IUse% Mounted on
/dev/sdb5               % /data
[root@localhost ~]#
           

将sdb5的inods值增加到350000(目前為327680),我的系統是rhel6.5,調整inode會格式化整個分區,分區将被删除,修改inode之後,uuid會被修改。是以,/etc/fstab檔案也需要作相應調整,最好先将該檔案cp備份一下

[[email protected] ~]# umount /data/    
[[email protected] ~]# mkfs.ext4 -N  /dev/sdb5   ;-N 指定要建立的inode數目。
mke2fs  (-May-)
Filesystem label=
OS type: Linux
Block size= (log=)
Fragment size= (log=)
Stride= blocks, Stripe width= blocks
 inodes,  blocks
 blocks (%) reserved for the super user
First data block=
Maximum filesystem blocks=
 block groups
 blocks per group,  fragments per group
 inodes per group
Superblock backups stored on blocks: 
    , , , , , , 

Writing inode tables: done                            
Creating journal ( blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every  mounts or
 days, whichever comes first.  Use tune2fs -c or -i to override.
[[email protected] ~]# tune2fs -j /dev/sdb5  ;tune2fs用來調整和檢視ext2/ext3/ext4)檔案系統的檔案系統參數,-j 将ext2檔案系統轉換為ext4類型的檔案系統
           
tune2fs  (-May-)
The filesystem already has a journal.
[root@localhost ~]# vim /etc/fstab 
#UUID=da86355c-7184-4c3a-8b3e-59429a9087eb /data ext4 defaults 0 0  ;開始的UUID
UUID=a03a11a1-bac2-cf4-ac97-b710f78c0a84 /data ext4 defaults  
[root@localhost ~]# mount -a
[root@localhost ~]# df -i /dev/sdb5
Filesystem     Inodes IUsed  IFree IUse% Mounted on
/dev/sdb5               % /data
[root@localhost ~]#
           

四、inode号碼

每個inode都有一個号碼,Unix/Linux系統内部不使用檔案名,而使用inode号碼來識别檔案。對于系統來說,檔案名隻是inode号碼便于識别的别稱或者綽号。表面上,使用者通過檔案名,打開檔案。實際上,系統内部這個過程分成三步:首先,系統找到這個檔案名對應的inode号碼;其次,通過inode号碼,擷取inode資訊;最後,根據inode資訊,找到檔案資料所在的block,讀出資料。

使用ls -i指令,可以看到檔案名對應的inode号碼:

[root@Zabbix_server zabbix]# ls -i indoe.txt 
 indoe.txt
[root@Zabbix_server zabbix]#
           

五、目錄檔案

Unix/Linux系統中,目錄(directory)也是一種檔案。打開目錄,實際上就是打開目錄檔案。

目錄檔案的結構非常簡單,就是一系列目錄項(dirent)的清單。每個目錄項,由兩部分組成:所包含檔案的檔案名,以及該檔案名對應的inode号碼。

ls指令隻列出目錄檔案中的所有檔案名,ls -i指令列出整個目錄檔案,即檔案名和inode号碼:

[root@Zabbix_server home]# ls ./zabbix/
indoe.txt
[root@Zabbix_server home]# ls ./zabbix/ -i
 indoe.txt
[root@Zabbix_server home]#
           

如果要檢視檔案的詳細資訊,就必須根據inode号碼,通路inode節點,讀取資訊。ls -l指令列出檔案的詳細資訊。

[root@Zabbix_server home]# ll ./zabbix/
total 
-rw-r--r--  root root  Aug  : indoe.txt
[root@Zabbix_server home]#
           

綜上,目錄檔案的讀權限(r)和寫權限(w),都是針對目錄檔案本身。由于目錄檔案内隻有檔案名和inode号碼,是以如果隻有讀權限,隻能擷取檔案名,無法擷取其他資訊,因為其他資訊都儲存在inode節點中,而讀取inode節點内的資訊需要目錄檔案的執行權限(x)。

六、硬連結

一般情況下,檔案名和inode号碼是”一一對應”關系,每個inode号碼對應一個檔案名。但是,Unix/Linux系統允許,多個檔案名指向同一個inode号碼。

這意味着,可以用不同的檔案名通路同樣的内容;對檔案内容進行修改,會影響到所有檔案名;但是,删除一個檔案名,不影響另一個檔案名的通路。這種情況就被稱為”硬連結”(hard link)。

ln指令可以建立硬連結:ln 源檔案 目标檔案

[root@Zabbix_server ~]# cat /home/zabbix/indoe.txt 
hard link
[root@Zabbix_server ~]# ll -i !$
ll -i /home/zabbix/indoe.txt
 -rw-r--r--  root root  Aug  : /home/zabbix/indoe.txt
[root@Zabbix_server ~]# ln !$ indoehl.txt
ln /home/zabbix/indoe.txt indoehl.txt
[root@Zabbix_server ~]# cat indoehl.txt 
hard link
[root@Zabbix_server ~]# ll -i indoehl.txt 
 -rw-r--r--  root root  Aug  : indoehl.txt
[root@Zabbix_server ~]# ll /home/zabbix/indoe.txt 
-rw-r--r--  root root  Aug  : /home/zabbix/indoe.txt
[root@Zabbix_server ~]# ll -i /home/zabbix/indoe.txt 
 -rw-r--r--  root root  Aug  : /home/zabbix/indoe.txt
[root@Zabbix_server ~]# rm -f indoehl.txt 
[root@Zabbix_server ~]# ll -i /home/zabbix/indoe.txt 
 -rw-r--r--  root root  Aug  : /home/zabbix/indoe.txt
[root@Zabbix_server ~]#
           

硬連結源檔案與目标檔案的inode号碼相同,都指向同一個inode。inode資訊中有一項叫做”連結數”,記錄指向該inode的檔案名總數,這時就會增加1。

反過來,删除一個檔案名,就會使得inode節點中的”連結數”減1。當這個值減到0,表明沒有檔案名指向這個inode,系統就會回收這個inode号碼,以及其所對應block區域。

建立目錄時,預設會生成兩個目錄項:”.”和”..”。前者的inode号碼就是目前目錄的inode号碼,等同于目前目錄的”硬連結”;後者的inode号碼就是目前目錄的父目錄的inode号碼,等同于父目錄的”硬連結”。是以,任何一個目錄的”硬連結”總數,總是等于2加上它的子目錄總數(含隐藏目錄)。

七、軟連結

檔案A和檔案B的inode号碼雖然不一樣,但是檔案A的内容是檔案B的路徑。讀取檔案A時,系統會自動将通路者導向檔案B。是以,無論打開哪一個檔案,最終讀取的都是檔案B。這時,檔案A就稱為檔案B的”軟連結”(soft link)或者”符号連結(symbolic link)。

這意味着,檔案A依賴于檔案B而存在,如果删除了檔案B,打開檔案A就會報錯:”No such file or directory”。這是軟連結與硬連結最大的不同:檔案A指向檔案B的檔案名,而不是檔案B的inode号碼,檔案B的inode”連結數”不會是以發生變化。

ln -s指令可以建立軟連結:ln -s 源文檔案或目錄 目标檔案或目錄

[root@Zabbix_server ~]# cat /home/zabbix/indoe.txt 
soft link
[root@Zabbix_server ~]# ll -i !$
ll -i /home/zabbix/indoe.txt
 -rw-r--r--  root root  Aug  : /home/zabbix/indoe.txt
[root@Zabbix_server ~]# ln -s !$ indoesl.txt
ln -s /home/zabbix/indoe.txt indoesl.txt
[root@Zabbix_server ~]# ll -i /home/zabbix/indoe.txt
 -rw-r--r--  root root  Aug  : /home/zabbix/indoe.txt
[root@Zabbix_server ~]# ll -i indoesl.txt 
 lrwxrwxrwx  root root  Aug  : indoesl.txt -> /home/zabbix/indoe.txt
[root@Zabbix_server ~]# cat indoesl.txt 
soft link
[root@Zabbix_server ~]# rm -f /home/zabbix/indoe.txt 
[root@Zabbix_server ~]# cat indoesl.txt 
cat: indoesl.txt: No such file or directory
[root@Zabbix_server ~]#
           

八、inode的特殊作用

由于inode号碼與檔案名分離,這種機制導緻了一些Unix/Linux系統特有的現象。

  1. 有時,檔案名包含特殊字元,無法正常删除。這時,直接删除inode節點,就能起到删除檔案的作用。

  2. 移動檔案或重命名檔案,隻是改變檔案名,不影響inode号碼。

  3. 打開一個檔案以後,系統就以inode号碼來識别這個檔案,不再考慮檔案名。是以,通常來說,系統無法從inode号碼得知檔案名。

擴充:

一般inode使用完是系統中建立了大量的小檔案導緻,例如日志檔案,隻是後我們可以到日志檔案目錄下去删除行不用的日志檔案

如果啟動了crond作業,系統中的郵件服務有沒開啟,由于linux在執行cron時,會将cron執行腳本中的output和warning資訊,都會以郵件的形式發送Cron所有者, 而由于客戶環境中的sendmail和postfix沒有正常運作,導緻郵件發送不成功,全部小檔案堆積在了/var/spool/postfix/maildrop目錄下面,如果sendmail或者postfix正常運作,則會在/var/mail目錄下産生大量的郵件,也會堆積。在cron的第一行加入 MAILTO=”“便可,這樣執行目前使用者的Cron時,不會發送郵件。

[root@localhost maildrop]# ll|wc -l

[root@localhost maildrop]# rm -rf * 
[root@localhost maildrop]# ls|xargs rm -rf
[root@localhost maildrop]# vim /etc/crontab 

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
#MAILTO=root
MAILTO=" "
HOME=/
[root@localhost maildrop]# service crond restart
           

如果無法确定位置可以通過逐層目錄查找來定位