很多线上服务器为了提供文件系统IO性能,会在挂载文件系统的时候指定“noatime,nodiratime”参数,意味着当访问一个文件和目录的时候,access time都不会更新。但是如果未指定上面的参数,atime则会更新。那么具体差异在哪里?

未指定 noatime,nodiratime

$ touch test ; stat test ;
...
Access: -- ::23.507135507 +
Modify: -- ::23.507135507 +
Change: -- ::23.507135507 + $ echo hello >> test ; stat test;
...
Access: -- ::23.507135507 +
Modify: -- ::38.018430637 +
Change: -- ::38.018430637 + $ cat test ;stat test
...
Access: -- ::02.916135510 +
Modify: -- ::38.018430637 +
Change: -- ::38.018430637 +

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

  1. read文件的时候会导致atime更新,不会导致mtime和ctime更新
  2. write文件只会导致mtime和ctime更新,不会导致atime更新。

指定 noatime,nodiratime

$touch test ; stat test ;
...
Access: -- ::28.680135484 +
Modify: -- ::28.680135484 +
Change: -- ::28.680135484 + $ sleep ; echo hello >> test ; stat test;
...
Access: -- ::28.680135484 +
Modify: -- ::38.682727983 +
Change: -- ::38.682727983 + $ cat test ;stat test
...
Access: -- ::28.680135484 +
Modify: -- ::38.682727983 +
Change: -- ::38.682727983 +

可以看出指定"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 + -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 {} \;

注:

上面是转载的原文,基本没有问题,但关于禁止文件和目录的访问时间,只需指定noatime即可,因为在linux内核中,当指定了noatime,关于nodiratime的判断也就自动跳过了。

下面是最新稳定版linux  4.13.3内核 中关于这段的代码说明:

bool __atime_needs_update(const struct path *path, struct inode *inode,
bool rcu)
{
struct vfsmount *mnt = path->mnt;
struct timespec now; if (inode->i_flags & S_NOATIME)
return false; /* Atime updates will likely cause i_uid and i_gid to be written
* back improprely if their true value is unknown to the vfs.
*/
if (HAS_UNMAPPED_ID(inode))
return false; if (IS_NOATIME(inode))
return false;
if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
return false; if (mnt->mnt_flags & MNT_NOATIME)
return false;
if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
return false; now = current_time(inode); if (!relatime_need_update(path, inode, now, rcu))
return false; if (timespec_equal(&inode->i_atime, &now))
return false; return true;
}

生产环境中的Linux内核多没有这么新,一般是2.6.32左右的,下面是2.6.32的linux内核关于这一点的说明:

void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct timespec now; 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; if (mnt->mnt_flags & MNT_NOATIME)
return;
if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
return; now = current_fs_time(inode->i_sb); if (!relatime_need_update(mnt, inode, now))
return; if (timespec_equal(&inode->i_atime, &now))
return; if (mnt_want_write(mnt))
return; inode->i_atime = now;
mark_inode_dirty_sync(inode);
mnt_drop_write(mnt);
}
EXPORT_SYMBOL(touch_atime);

通过查看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. MS_RELATIME (Since Linux 2.6.)
When a file on this file system is accessed, only update the file’s last access time (atime) if the current value
        of atime is less than or equal to the file’s last modification time (mtime) or last status change time (ctime).
        This option is useful for programs, such as mutt(), that need to know when a file has been read since it was last modified.
        Since Linux 2.6., the kernel defaults to the behavior provided by this flag (unless MS_NOATIME was specified),
        and the MS_STRICTATIME flag is required to obtain traditional semantics.In addition, since Linux 2.6., the file’s last
        access time is always updated if it is more than day old. MS_STRICTATIME (Since Linux 2.6.)
Always update the last access time (atime) when files on this file system are accessed.
        (This was the default behavior before Linux 2.6..) Specifying this flag overrides the effect
        of setting the MS_NOATIME and MS_RELATIME flags.

通过判定MS_NODIRATIME,如果为真,就不再更新目录的访问时间。

上面参数中提到了MS_RELATIME,对于某些用户某些应用,atime 信息可能是必要的,比如邮件程序和备份工具。如果完全禁止 atime 更新会使这些程序无法正常工作。针对这种情况,Linux 在内核 2.6.20 中添加了一个新的 mount 选项 relatime(relative atime 的意思)。relatime 的意思是访问文件时,仅在 atime 早于文件的更改时间时对 atime 进行更新。在内核 2.6.24 中,又对 relatime 进行了扩展,在访问文件时,当 atime 已经超过某个时间(例如一天)没有更新,就对 atime 进行更新。这个扩展的意思就是调整 atime 的更新粒度。

下面是mount(8)中的参数说明:

relatime
Update inode access times relative to modify or change time. Access time is only updated if the previous access
         time was earlier than the current modify or change time. (Similar to noatime, but doesn’t break mutt or
         other applications that need to know if a file has been read since the last time it was modified.) Since Linux 2.6., the kernel defaults to the behavior provided by this option (unless noatime was specified),
         and the strictatime option is required to obtain traditional semantics. In addition, since Linux 2.6., the
         file’s last access time is always updated if it is more than day old. strictatime
Allows to explicitly requesting full atime updates. This makes it possible for kernel to defaults to
        relatime or noatime but still allow userspace to override it. For more details about the default system mount
        options see /proc/mounts.

使用 relatime(relative atime)挂载,可在前一个 atime 更新比 mtime 或者 ctime 更新旧时更新 atime。

在这个示例中,GFS2 文件系统位于 /dev/vg01/lvol0,并挂载到目录 /mygfs2。只有在前一个 atime 更新比 mtime 或者 ctime 更新旧时才会进行 atime 更新。

mount /dev/vg01/lvol0 /mygfs2 -o relatime

参考资料:

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

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

https://mp.weixin.qq.com/s?__biz=MzA3MzYwNjQ3NA==&mid=400742435&idx=1&sn=d5fa0776ebce30be1de897cd7d1eb295&scene=1&srcid=1123K3Ka8EtwjcNXhNfUGJV7#rd

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/fs/inode.c?h=v4.13.3

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/fs/inode.c?h=linux-2.6.32.y

理解Linux文件系统挂载参数noatime nodiratime的更多相关文章

  1. Linux 文件系统挂载

    文件系统挂载简介  磁盘分区和格式化完成后,磁盘分区要想能够使用,就需要挂载,在挂载某个分区前需要先建立一个挂载点  挂载:将新的文件系统关联至当前根文件系统  卸载:将某文件系统与当前根文件系统的关 ...

  2. Linux入门基础 #5:Linux文件系统挂载管理

    本文出自   http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...

  3. Linux文件系统挂载管理

    http://itercast.com/lecture/19 文件系统创建好之后需要挂载到系统中方可使用,windows.Mac系统会自动挂载文件系统,而Linux下一般需要手工挂载或配置系统进行自动 ...

  4. 理解Linux文件系统之inode

    很少转发别人的文章,但是这篇写的太好了. 理解inode   作者: 阮一峰 inode是一个重要概念,是理解Unix/Linux文件系统和硬盘储存的基础. 我觉得,理解inode,不仅有助于提高系统 ...

  5. [转]理解Linux文件系统之inode

    很少转发别人的文章,但是这篇写的太好了. 理解inode   作者: 阮一峰 inode是一个重要概念,是理解Unix/Linux文件系统和硬盘储存的基础. 我觉得,理解inode,不仅有助于提高系统 ...

  6. Linux 入门记录:九、Linux 文件系统挂载管理

    一.挂载操作 磁盘或分区创建好文件系统后,需要挂载到一个目录才能够使用. Windows 或 Mac 系统会进行自动挂载,一旦创建好文件系统后会自动挂载到系统上,Windows 上称之为 C 盘.D ...

  7. linux文件系统挂载

    接上一篇博客 创建好了文件系统的磁盘仍然是不能用的,必须挂载到某个目录下才能使用 [root@gechong mnt]# ll /dev/sdb* brw-rw----. root disk , 11 ...

  8. 理解Linux文件系统之 inode

    一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做”扇区”(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统读取硬盘的时候,不会 ...

  9. 深入理解Linux文件系统与日志分析

    一.inode和bolck概述 二.链接文件 三.inode节点耗尽故障处理 四.EXT类型文件恢复 五.xfs文件备份和恢复 六.日志文件 一.inode和bolck概述 1.定义 文件数据 文件数 ...

随机推荐

  1. Django - day01 快速回忆ORM操作

    Django - day01 Model的增删改查找 得益于Django的ORM模型,用面向对象的思想来操作数据库使得数据库的操作一切变得简洁了很多. 0. 建表 在应用下的models.py中建立一 ...

  2. TW实习日记:第18天

    今天的bug没有那么多了,都是些小bug,一下就改好了.或者是接口那边数据返回的有问题,通知一下同事就ok了.主要今天是在赶功能进度,然而有一个功能模块需求里并没有写,实在是不知道要做成什么样子,真的 ...

  3. 【python 3.6】从网站抓图并存放到本地路径

    #!/usr/bin/python # -*- coding: UTF-8 -*- _author_ = 'BH8ANK' import urllib.request import re import ...

  4. ubuntu server guide 学习笔记

    1. 软件包 1.1. dpkg dpkg -l dpkg -l | grep apache2 dpkg -L ufw dpkg -S /etc/host.conf dpkg -i zip_3.0-4 ...

  5. PHP正则相关

    描述字符串排列模式的一种自定义语法规则 如果可以使用字符串函数处理的任务 就不要使用正则 正则表达式 就是通过构建具有特定规则的模式,与输入的字符信息比较 在进行 分割 匹配 查找 替换 等工作   ...

  6. 基于spring-boot、spring-cloud的websocket服务器多点负载均衡改造

    背景 为应对更多用户使用socket的场景,准备对存放websocket的服务器进行多点搭建并配置负载均衡. 问题 服务器上了多点负载均衡以后,基于socket的部分功能发生了有规律的失效,查看后台日 ...

  7. A4

    队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 很胖,刚学,照猫画虎做了登录与注册界面. 展示GitHub ...

  8. iOS开发热更新JSPatch

    JSPatch,只需在项目中引入极小的引擎,就可以使用JavaScript调用任何Objective-C的原生接口,获得脚本语言的能力:动态更新APP,替换项目原生代码修复bug. 是否有过这样的经历 ...

  9. C# Winform防止闪频和再次运行

    其实想实现只允许运行一个实例很简单,就是从program的入口函数入手.有两种情况: 第一种,用户运行第二个的时候给一个提示: using System; using System.Collectio ...

  10. 3dContactPointAnnotationTool开发日志(十)

      要是那几个状态栏不能拖动的话岂不是显得太呆板了,于是我又参考Unity官方视频教程学习了如何实现拖动状态栏的功能,还挺简单的.   比如说要拖动这个PanelStatus面板,我只让使用者通过拖动 ...