<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          刪除文件為啥磁盤依然爆滿

          共 3281字,需瀏覽 7分鐘

           ·

          2021-03-20 10:32

          01


          問題發(fā)現(xiàn)


          最近在測試遇到一個問題,容器日志過大導(dǎo)致系統(tǒng)磁盤爆滿,造成的影響就是該服務(wù)器的一些服務(wù)掛掉了。日志過大,解決方法就是刪啊,直接定位到容器日志位置發(fā)現(xiàn)高達5G,三下五除二就rm了,但是仍然顯示磁盤空間已滿,但是du -sh命令也顯示文件夾下為空。經(jīng)過同事百度得知,容器日志不能直接rm,要通過cat /dev/null > {log文件}方式將日志刪除。因為該文件被進程所引用,直接刪除并不能擦除磁盤上的文件block信息,解決方式就是停止進程。今天就來復(fù)現(xiàn)一下并探究一下底層原理。

          02


          設(shè)計復(fù)現(xiàn)


          由于容器也屬于一種進程,引用文件的方式并沒有不同于其他普通進程,所以就使用一個簡單的demo復(fù)現(xiàn)。

          首先進入一個目錄,以/tmp/testfile目錄為例,可以看到我的服務(wù)器還有2G的剩余空間

          [centos@guozhao testfile]$ cd /tmp/testfile
          [centos@guozhao testfile]$ df -h .
          文件系統(tǒng)       容量 已用 可用 已用% 掛載點
          /dev/vda1       50G   49G  2.0G   97% /

          然后生成一個隨機文件,再來查看剩余空間,看到還剩余1014M空間

          [centos@guozhao testfile]$ dd if=/dev/urandom of=/tmp/testfile/delfiletest   bs=1M count=1000
          記錄了1000+0 的讀入
          記錄了1000+0 的寫出
          1048576000字節(jié)(1.0 GB)已復(fù)制,8.31491 秒,126 MB/秒
          [centos@guozhao testfile]$
          [centos@guozhao testfile]$ df -h .
          文件系統(tǒng)       容量 已用 可用 已用% 掛載點
          /dev/vda1       50G   49G 1014M   99% /

          啟動一個程序,引用該文件,不退出進程

          func main() {
              file, err := os.Open("/tmp/testfile/delfiletest")
              defer file.Close()
              if err != nil{
              fmt.Println("open err :",err.Error())
              return
              }
              time.Sleep(100*time.Minute)
          }

          接下來刪除該文件文件,查看磁盤占用情況,看到雖然文件刪除,但是磁盤空間并沒有釋放。

          [centos@guozhao testfile]$ rm -rf delfiletest
          [
          centos@guozhao testfile]$ df -h .
          文件系統(tǒng)       容量 已用 可用 已用% 掛載點
          /dev/vda1       50G   49G 1015M   99% /

          解決方法,找到引用該文件的進程,并停止該進程,可以Ctrl+C停止,也可以kill命令停止。

          [centos@guozhao testfile]$ lsof | grep deleted|grep delfile
          l
          sof: WARNING: can't stat() proc file system /run/docker/netns/default
              Output information may be incomplete.
          ......
          testdelet 29604 29608 centos   3r     REG  253,1 1048576000 58925156 /tmp/testfile/delfiletest (deleted)
          ......
          [centos@guozhao testfile]$ kill 29604

          停止后再次查看磁盤空間,發(fā)現(xiàn)磁盤已經(jīng)釋放。

          [centos@guozhao testfile]$ df -h .
          文件系統(tǒng)       容量 已用 可用 已用% 掛載點
          /dev/vda1       50G   49G  2.0G   97% /

          重做一次上面的步驟,這次我們使用正確的方式釋放磁盤的空間,可以看到磁盤空間騰出來了。

          [centos@guozhao testfile]$ cat /dev/null > /tmp/testfile/delfiletest 
          [centos@guozhao testfile]$
          [centos@guozhao testfile]$ df -h .
          文件系統(tǒng)       容量 已用 可用 已用% 掛載點
          /dev/vda1       50G   49G  2.0G   97% /

          03


          原理考究


          繼續(xù)深挖一下造成這種結(jié)果的原因。

          在Linux上,每個文件都有一個自己對應(yīng)的索引節(jié)點即inode,在這個inode里記錄了文件在磁盤的塊信息,以及鏈接數(shù)量等信息,一個文件在是否要被真正刪除釋放空間,取決于兩個值,一個是 i_count ,代表引用計數(shù);一個是 i_nlink ,代表硬鏈接數(shù)量,只有當(dāng)兩個都為0,文件才會真正釋放。

          struct inode{
             atomic_t i_count;
             unsignet int i_nlink;
            ......
          };

          當(dāng)有進程使用該文件時候, i_count 就會加1,當(dāng)進程不在引用或進程結(jié)束,就會減一。

          硬鏈接也是如此,當(dāng)為文件創(chuàng)建一個硬鏈接時, i_nlink 就會加一,刪除就會減一,當(dāng)減少為0時候,就會刪除文件,釋放空間。

          在Linux中,硬鏈接指的是文件名與inode的鏈接,通常創(chuàng)建一個文件對應(yīng)一個硬鏈接,我們可以手動通過ln命令或者程序觸發(fā)link系統(tǒng)調(diào)用為一個文件創(chuàng)建一個硬鏈接,相當(dāng)于兩個文件名對應(yīng)了同一個磁盤文件,兩個都刪除才會刪除磁盤文件(沒有進程引用的前提下)。而Linux的rm命令相當(dāng)于執(zhí)行了unlink系統(tǒng)調(diào)用,會使得i_nlink數(shù)量減1。

          在上述示例中,由于文件并沒有被真正刪除,所以該文件是可以恢復(fù)的,只需要找到進程的pid,并進入 /proc/{pid}/fd 中,找到對應(yīng)的文件描述符,執(zhí)行 cp 命令復(fù)制即可找回文件。



          推薦閱讀


          福利

          我為大家整理了一份從入門到進階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門看什么,進階看什么。關(guān)注公眾號 「polarisxu」,回復(fù) ebook 獲??;還可以回復(fù)「進群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。

          瀏覽 59
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲在线电影院日韩 | 国产精品人妻无码一区牛牛影视 | 乌克兰一级操逼片 | 九色PORNY9l原创自拍 | 精品一区二区视频在线观看 |