關於 mount掛載時候的參數 noatime nodiratime 的一些說明

  • 2019 年 10 月 4 日
  • 筆記

以下內容來自2篇部落格,地址分別是:

http://www.firefoxbug.com/index.php/archives/2801/

https://www.cnblogs.com/allegro/archive/2011/04/18/2019598.html

1 理解Linux文件系統掛載參數noatime nodiratime

很多線上伺服器為了提供文件系統IO性能,會在掛載文件系統的時候指定「noatime,nodiratime」參數,意味著當訪問一個文件和目錄的時候,access time都不會更新。但是如果未指定上面的參數,atime則會更新。那麼具體差異在哪裡?

未指定 noatime,nodiratime

$ touch test ; stat test ;  ...  Access: 2015-04-04 00:37:23.507135507 +0800  Modify: 2015-04-04 00:37:23.507135507 +0800  Change: 2015-04-04 00:37:23.507135507 +0800    $ echo hello >> test ; stat test;  ...  Access: 2015-04-04 00:37:23.507135507 +0800  Modify: 2015-04-04 00:37:38.018430637 +0800  Change: 2015-04-04 00:37:38.018430637 +0800    $ cat test ;stat test  ...  Access: 2015-04-04 00:38:02.916135510 +0800  Modify: 2015-04-04 00:37:38.018430637 +0800  Change: 2015-04-04 00:37:38.018430637 +0800

可以看出未指定"noatime,nodiratime"的情況下

  1. read文件的時候會導致atime更新,不會導致mtime和ctime更新
  2. write文件只會導致mtime和ctime更新,不會導致atime更新。

指定 noatime,nodiratime

$touch test ; stat test ;   ...  Access: 2015-04-04 00:28:28.680135484 +0800  Modify: 2015-04-04 00:28:28.680135484 +0800  Change: 2015-04-04 00:28:28.680135484 +0800    $ sleep 10 ; echo hello >> test ; stat test;  ...  Access: 2015-04-04 00:28:28.680135484 +0800  Modify: 2015-04-04 00:28:38.682727983 +0800  Change: 2015-04-04 00:28:38.682727983 +0800    $ cat test ;stat test  ...  Access: 2015-04-04 00:28:28.680135484 +0800  Modify: 2015-04-04 00:28:38.682727983 +0800  Change: 2015-04-04 00:28:38.682727983 +0800

可以看出指定"noatime,nodiratime"的情況下

  1. read文件的時候不會導致atime、mtime、ctime改變
  2. write文件只會導致mtime和ctime更新,不會導致atime更新。

實際應用場景

在平日里經常有刪除文件的需求,大概如下

刪除過去N天內都未訪問過的文件或者目錄(刪除N天前訪問過的文件)    $ #注意這條命令很危險!   $ find /home/fire/ -atime +N -exec rm -rf {} ;

假設 /home/fire 目錄是一周之前創建的,那麼對於這條命令有兩個執行結果

$ #注意這條命令很危險!   $ find /home/fire/ -atime +7 -exec rm -rf {} ;
  • 指定"noatime":find的時候發現 /home/fire 是7天之前創建的,立馬就會刪除整個目錄。而且還會報錯"find: /home/fire: No such file or directory",原因就是第一個rm -rf /home/fire 之後 find失敗了。這種是很危險的!原因是會誤刪除文件。
  • 未指定"noatime":那就得看情況,如果/home/fire過去7天沒有被訪問過,那麼就和情況一一樣,直接刪除。如果過去7天內,該目錄有人訪問過,atime肯定是7天之內,那麼就會遍歷下面的目錄,依次按照之前邏輯。但是遍歷過程會更改目錄的atime。

看了上面的例子會發現find去刪除目錄的時候變得好複雜,而且一定要小心。所以find刪除更適用於刪除文件,不要刪除目錄。

刪除N天內未被訪問過的文件  $ find /home/fire/ -atime +N -type f -exec rm -f {} ;

2 我們需要同時設置noatime和nodiratime嗎?很多資料都提到要同時設置noatime和nodiratime,但我們看mount(2)關於參數的描述: 

MS_NOATIME         Do not update access times for (all types of) files on this file         system.  MS_NODIRATIME         Do  not update access times for directories on this file system.         This flag provides a subset of  the  functionality  provided  by         MS_NOATIME; that is, MS_NOATIME implies MS_NODIRATIME.

 如何理解這裡的「(all types of) files」,目錄是否作為文件的一類?

    還是看看內核源碼的相關內容,在文件fs/inode.c中有個touch_atime函數:

void touch_atime(struct vfsmount *mnt, struct dentry *dentry)  {      /* ... */      if (inode->i_flags & S_NOATIME)          return;      if (IS_NOATIME(inode))          return;      if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))          return;

 可以看到,一旦NOATIME標誌位設置,NODIRATIME就不再被處理了。

    而且Andrew Morton同學也說了:"noatime is a superset of nodiratime, btw."

    好了,大家知道該怎麼做了吧。

結論: mount掛載的時候,只用 noatime即可,不用加 nodiratime。