资讯详情

资讯详情

Linux 文件时间戳:atime、mtime、ctime 与 find 实战

干了几年运维被问得最多的一个问题就是“这文件到底什么时候被动过”。很多人第一反应是ls -l看时间但那一列只是三个时间戳里的一个而且经常不是你想找的那个。Linux 里每个文件在 inode 上都挂着atime、mtime、ctime三个时间分别记录访问、内容修改、元数据变更再加上新内核支持的 birth time。搞不清它们的分工排查问题时就会一直在错误的方向上打转明明没人动过配置文件mtime 却变了明明只是cat了一下备份脚本却全量重传明明用touch把时间改回去了审计脚本还是报“文件刚刚被修改”。这篇文章会把这三个时间的更新条件、内核里的存储方式、挂载选项对它们的实际影响讲透然后把find的时间查找和touch的时间修改掰开揉碎配上可以直接抄走的命令和我在生产环境踩过的坑。刚接触 Linux 的朋友可以照着命令敲一遍有几年经验的老手建议重点看 relatime 和 ctime 那两段很多“玄学问题”的答案都在那里。1. 三个时间到底是什么从一次配置漂移排查说起1.1 用 stat 把 inode 上的时间字段摊开看判断文件时间最靠谱的工具不是ls而是stat。它直接把 inode 里的字段打印出来不会被任何显示层的默认行为干扰$ stat /etc/nginx/nginx.conf File: /etc/nginx/nginx.conf Size: 2652 Blocks: 8 IO Block: 4096 regular file Device: fd01h/64769d Inode: 787456 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2024-05-12 09:14:22.138927841 0800 Modify: 2024-05-10 21:03:47.512004119 0800 Change: 2024-05-12 09:14:22.138927841 0800 Birth: 2024-03-01 11:22:05.771340221 0800四个字段对应关系一目了然Access是 atimeModify是 mtimeChange是 ctimeBirth是文件创建时间crtime也叫 birth time。注意纳秒精度是跟着文件系统走的ext4、xfs 支持到纳秒NFS、FAT 这类往往只到秒跨文件系统拷贝之后精度会掉。ls其实也能看全只是要加参数ls -lu看 atimels -l默认看 mtimels -lc看 ctimels -l --timebirth看创建时间。我在写脚本时更愿意用stat的格式化输出字段固定、便于解析$ stat -c %n | atime%x | mtime%y | ctime%z /etc/nginx/nginx.conf /etc/nginx/nginx.conf | atime2024-05-12 09:14:22.138927841 0800 | mtime2024-05-10 21:03:47.512004119 0800 | ctime2024-05-12 09:14:22.138927841 0800其中%x、%y、%z、%w分别对应 atime、mtime、ctime、birth%X、%Y、%Z输出的是 Unix 时间戳秒数。要拿时间戳做数值比较时用大写那几个省事得多。1.2 谁更新了谁三个时间的触发条件对照这三个时间最容易被混为一谈其实触发条件完全不同时间英文全称触发时机典型操作能否手动指定atimeaccess time读取文件内容cat、grep、less、执行脚本、read系统调用可以touch -amtimemodify time文件内容被写入编辑器保存、追加、truncate、dd覆盖可以touch -m -dctimechange timeinode 元数据发生变化chmod、chown、ln、mv、改 mtime/atime 本身不能直接指定crtimebirth time文件被创建新建文件、重定向创建不能直接指定有三条规律必须刻在脑子里。第一条改 mtime 一定会连带改 ctime因为 mtime 本身就是 inode 里的一个字段写它等于改元数据。这条规律解释了为什么touch改完时间之后审计工具仍然能看出文件“被动过”。第二条读文件不一定更新 atime具体看挂载选项这个后面单独讲。第三条目录也是文件目录的 mtime 在目录里新增、删除、重命名条目时更新目录的 atime 在ls、readdir这类遍历操作时更新。所以看到目录 mtime 变了不代表目录里的文件内容变了很可能只是有人往里丢了一个新文件。我遇到过一次典型的误判同事发现/etc/supervisor/conf.d/这个目录的 mtime 是今天立刻断定有人偷偷改了配置。实际查下来只是有个部署脚本往这个目录里塞了一个新配置片段老文件一个都没动。这种场景下正确的做法是先stat目录重点看目录里每个文件的 mtime再结合ctime和审计日志判断而不是被目录的 mtime 牵着走。1.3 为什么 ctime 是唯一“改不掉”的时间ctime 由内核在 inode 更新时写入没有任何标准系统调用允许用户直接指定它。这意味着在数字取证和变更审计里ctime 的可信度远高于 mtime。一个人可以轻松把 mtime 改成三年前但 ctime 永远停留在“刚刚被改过”的时刻——这个矛盾本身就是证据。理论上能不能改对 ext2/ext3/ext4 这一系文件系统debugfs可以直接操作 inode 字段包括 ctime。但这玩意儿要求文件系统处于卸载状态或者只读挂载操作中一旦手抖就是文件系统损坏、数据全丢。我在生产环境从来不碰它也建议你把这条路当作知识边界了解即可不要真的去用。真正需要“文件变更历史可追溯”的场景正确解法是在应用层做记录auditd 审计规则、把元数据写进数据库、或者干脆用版本控制系统管理配置都比依赖文件时间戳可靠。顺带说一个容易混淆的点同样是“移动文件”mv在同一个文件系统内和跨文件系统时行为完全不同。同一个文件系统内mv只改目录项mtime 和 atime 原样保留只有 ctime 会变成当前时间跨文件系统时mv实际是“复制 删除”如果内部调用的是不带保留参数的复制mtime 就变成复制时刻了。所以脚本里跨盘搬文件老老实实写cp -a再rm别指望mv帮你保住时间。2. 时间戳背后的内核机制与常见误区2.1 inode 上的时间字段是怎么被写进去的ext4 的 inode 结构里保存着i_atime、i_mtime、i_ctime三个时间字段创建时间i_crtime放在 inode 的扩展区域。每次文件操作走到最后内核都会调用类似current_time()的函数取当前时间写进对应字段并把这个 inode 标记为脏交给回写线程刷盘。这里有个容易被忽略的细节inode 的写入是异步延迟的。文件内容写完数据可能先进 page cache时间字段的更新会随元数据一起在几秒到几十秒后落盘。正常运行看不出来但如果刚cat完一个文件就断电重启重启后 atime 有可能还是旧的。同理用stat看到的永远是内存里那份即时值跟磁盘上的那份在极端情况下会不一致。还有一类情况是“操作没走到 inode 更新这一步”。比如只打开文件不读内容open后直接closeatime 是否更新取决于是否真的发生了read再比如mmap映射只读访问atime 的更新时机跟普通read也不完全一样。排查时间异常时如果发现某个文件的 atime 一整天没变过先确认这个程序到底有没有真正读到数据而不是直接怀疑文件系统坏了。2.2 relatime 与 noatimeatime 为什么总是不准这是被问得最多的问题“我明明cat过这个文件了为什么 atime 没变”答案是挂载选项。Linux 内核从 2009 年前后开始把relatime作为默认选项规则是这样的只有当 atime 早于 mtime 或 ctime或者 atime 距今已经超过 24 小时才会真正去更新 atime。其余情况一律跳过更新省掉大量无谓的 inode 写操作。其他几个相关选项挂载选项行为适用场景strictatime/atime每次读取都更新 atime审计要求严格、读操作不密集relatime满足条件才更新默认绝大多数通用场景noatime完全禁止更新 atime读多写多、追求 IO 性能nodiratime只禁止目录的 atime 更新想减少目录遍历开销查当前挂载选项$ findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS / TARGET SOURCE FSTYPE OPTIONS / /dev/sda1 ext4 rw,relatime,errorsremount-ro想临时改成严格模式验证一下mount -o remount,strictatime /。想持久化就改/etc/fstab第四列但改 fstab 是个高危操作写错了机器可能起不来。稳妥流程是先用mount -o remount,...测试效果确认没问题再把选项写进 fstab写完用mount -a验证一遍最后再重启确认。虚拟机或者有带外管理通道的机器上折腾这个比较安全纯远程物理机我一般会先备份 fstab。noatime的收益在特定场景下很可观。我手上有台跑静态资源的机器几百万个小文件、大量随机读把数据盘改成noatime之后 iowait 有肉眼可见的下降。但代价是 atime 彻底不可用了如果有归档工具靠 atime 判断“这个文件被读过没有”比如某些备份策略会归档“已读取但未修改”的文件那就千万别关。选之前先问清楚业务依赖什么。注意relatime是默认值这件事是很多人排查 atime 问题时最大的认知盲区。看到 atime 不更新先查挂载选项再去怀疑别的。2.3 五个高频误区我全都踩过第一拿ls -l判断文件是否被读取过。ls -l显示的是 mtime要看访问时间得用ls -lu。这个错误我在刚工作时犯过还煞有介事地跟同事解释场面相当尴尬。第二以为 ctime 是创建时间。太多教程这么写了。ctime 的 c 是 change不是 create。创建时间要看 birth time而且它需要内核和文件系统同时支持才能读出来。第三以为mv不会改任何时间。同文件系统内确实不改 mtime 和 atime但 ctime 一定会变因为目录项发生了变化。有次做文件完整性校验脚本只比对 mtime结果文件被挪了位置也没报出来。第四以为touch改完时间就“洗白”了。mtime 能改atime 能改ctime 原地不动永远是刚刚。凡是对接审计的流程靠touch是糊弄不过去的。第五以为find -mtime 7就是“7 天以前”。这个语义比直觉复杂下一节专门拆。3. 查找用 find 按时间精准定位文件3.1 -atime/-mtime/-ctime 的语义与正负号陷阱find的时间判断跟“天数”这个概念是错位的它算的是完整 24 小时的整数倍数。内核的做法是拿当前时间减去文件时间得到秒数差除以 86400 再向下取整得到一个整数 d然后拿 d 去跟参数比较-mtime nd n也就是时间差落在第 n 个 24 小时区间内-mtime -nd n不足 n 天-mtime nd n超过 n 天关键就在n这里。-mtime 7的含义是d 7也就是至少 8 天而不是“7 天以前”。想要“7 天以前”的精确表达用-newermt指定绝对时间更清楚。这个偏差在清理任务里非常致命你以为删的是 8 天前的文件实际可能少删了一批或者反过来多删。常用组合列一下# 24 小时内修改过的文件 find /data -type f -mtime -1 # 修改时间落在 1 到 2 天之间的文件 find /data -type f -mtime 1 # 超过 30 天没修改过的文件 find /data -type f -mtime 30 # 5 分钟内 ctime 变化过的文件权限、属主被动过 find /data -type f -cmin -5 # 只看今天 00:00 之后修改的-daystart 改变起点 find /data -type f -mtime -1 -daystart分钟级参数-amin、-mmin、-cmin语义跟天数版本完全一致只是单位换成分钟每次被调用都会根据当前时间重新取值非常适合排查“刚刚发生了什么”。3.2 -newer、-newermt 与 -newerXY 的进阶玩法只要涉及绝对时间我就优先用-newermt它让脚本可读性提升一个档次# 找出 2024-05-01 之后修改过的文件 find /data -type f -newermt 2024-05-01 # 5 月 1 日到 5 月 10 日之间改动的文件 find /data -type f -newermt 2024-05-01 ! -newermt 2024-05-10 # 今天改动的文件 find /data -type f -newermt today-newer系列还有个很好用的形式-newerXY。规则是X 表示“被检查文件的哪个时间”Y 表示“参考值的来源”X 可取a、c、mY 可取a、c、m、tt表示参考值直接写时间字符串。所以-newermt就是 Xm、Yt 的组合。-anewer ref等价于-neweram比较的是被检查文件的 atime 和参考文件的 mtime-cnewer ref等价于-newercm。这里面有个杀手级用法区分“内容被改”和“权限被改”。# 最近 10 分钟 ctime 变过但 mtime 没变 —— 大概率只是 chmod/chown find /data -type f -cmin -10 ! -mmin -10反过来也成立找“内容改了且权限也顺手改了”的文件就两个条件同时加。排查配置漂移时这个组合能帮你快速锁定到底是部署脚本在动内容还是某个权限收敛任务在动元数据。还有个细节值得强调-newermt的时间解析依赖本地时区。服务器在 UTC、你人在 08:00脚本里写-newermt 2024-05-01实际比较的起点可能跟你想的差 8 小时。脚本里统一加时区或者用 UTC 时间串能省掉一堆对不上的麻烦TZUTC find /data -type f -newermt 2024-05-01 00:00:003.3 生产环境常用的查找组合速查下面这些是我日常真在用的命令直接抄改路径就能跑需求命令清理 30 天前的日志find /var/log/app -type f -name *.log -mtime 30 -delete先看再删确认无误再执行find /var/log/app -type f -mtime 30 -print -exec ls -lh {} \;找出 7 天内改过的配置文件find /etc -type f -mmin -10080找出只被改过权限的文件find /data -type f -cmin -60 ! -mmin -60统计而不是立即删除find /data -type f -mtime 7 | wc -l排除某个目录再找find /data -path /data/cache -prune -o -type f -mtime 7 -print处理带空格的文件名find /data -type f -name *.tmp -print0 | xargs -0 rm -f打包指定时间范围的文件find /data -type f -newermt 2024-05-01 ! -newermt 2024-05-10 -print0 | tar --null -T - -czf range.tar.gz使用-delete时有几个坑。它会隐含-depth也就是先处理子目录内容再处理目录本身这跟-prune一起用会失效因为-prune依赖深度优先的反向顺序另外-delete不做任何确认路径写错就是灾难。我的习惯是永远先跑一遍-print或者-print | wc -l确认数量对了再把-print换成-delete。多敲两行命令能省掉一次事故复盘。-exec的两种写法也要分清-exec cmd {} \;对每个文件单独起一个进程几万个文件能跑很久-exec cmd {} 会把文件攒成一批传进去性能好得多。能用就别用\;。4. 修改怎么把时间戳改成想要的值4.1 touch 的完整参数与时间格式touch是最常用的时间修改工具但它远不止“改当前时间”这一个功能touch file # 文件不存在就创建存在则把 atime、mtime 设为当前 touch -a file # 只把 atime 设为当前 touch -m file # 只把 mtime 设为当前 touch -t 202405011030.00 file # 指定时间格式 [[CC]YY]MMDDhhmm[.ss] touch -d 2024-05-01 10:30:00 file touch -d 2 days ago file touch -d yesterday file touch -r ref.conf file # 复制 ref.conf 的时间戳到 file touch -h symlink # 作用于软链接本身而不是它指向的目标 touch -c file # 文件不存在时不创建静默跳过-t的格式看起来像一串数字拆开读就是“年月日时分秒”202405011030.00表示 2024 年 5 月 1 日 10 点 30 分 00 秒。-d更灵活支持 GNU date 的解析规则2 days ago、last week、2024-05-01T10:30:00都能认。有两点要注意。一是-t的时间按本地时区解释服务器时区变了同一个命令产生的绝对时间就变了跨机器同步文件时容易出岔子。二是-d的自然语言解析在不同发行版、不同语言环境LC_ALL下表现不一致yesterday这种写法在 C 语言环境下没问题但生产脚本里我从来不用一律写绝对时间可读性差一点确定性高很多。-r是我最喜欢的参数因为它能规避格式与时区问题与其手写时间字符串不如拿一个“时间基准文件”当模板把它的时间戳克隆到目标文件上。批量恢复文件时间时这招比-d靠谱得多。4.2 批量修改、目录与符号链接的处理单个文件改时间很简单批量操作才是真需求。几种常见写法# 把一批文件的时间改成跟模板文件一致 find /data/new -type f -exec touch -r /data/template.conf {} # 把整个目录树的时间戳按参考目录对齐目录本身也要处理 find /data/new -exec touch -r /data/old/template.conf {} # 只改 mtime保留 atime 不动 find /data/new -type f -exec touch -m {} # 把所有文件的时间往前调一天 find /data/new -type f -exec touch -d $(date -d yesterday %Y-%m-%d %H:%M:%S) {} 目录的处理要特别留意touch dir只会改目录本身的时间不会递归到里面的文件touch -r dir1 dir2也只是把dir2这一个目录的时间对齐子文件原样不动。想整个目录树对齐必须用find遍历而且别忘了目录本身——find默认会输出目录条目所以上面第二条命令里我没有加-type f就是为了连目录一起处理。符号链接是另一个坑。默认情况下touch会跟随软链接改的是目标文件的时间要改链接本身得加-h。这个功能依赖文件系统支持lutimes绝大多数现代文件系统没问题。链接本身的时间平时不太重要但在做镜像或者复刻文件树时链接的 mtime 也会被对比出来那时候就需要-h。文件系统还会带来一个隐形的差异硬链接。硬链接指向同一个 inode改任何一个路径的时间所有路径的时间同时变。如果你发现“明明只改了一个文件另一个毫不相干的路径时间也变了”先检查这俩是不是硬链接ls -li看 inode 号是否相同别急着怀疑系统抽风。4.3 改完之后怎么验证以及 ctime 的硬边界改完时间一定要验证不能想当然$ touch -m -d 2023-01-01 00:00:00 app.log $ stat -c atime%x mtime%y ctime%z app.log atime2024-05-12 09:20:31.002139402 0800 mtime2023-01-01 00:00:00.000000000 0800 ctime2024-05-12 09:20:31.002139402 0800结果很清楚mtime 回到了 2023 年atime 和 ctime 都停在刚刚。这就是前面反复说的那条边界——mtime 可改ctime 不可改。任何依赖 ctime 做变更检测的逻辑都会在touch之后立刻报警这不是 bug是设计如此。如果确实遇到“需要一个老文件树、连 ctime 都要对得上”的场景正规路子是在应用层面解决把元数据创建时间、变更历史存进数据库或者用版本控制系统管理这批文件让时间戳只作为辅助参考。用debugfs直接改 inode 这条路能走通但代价是文件系统必须卸载或只读挂载操作窗口长、风险高我在任何线上环境都不会采用这里列出来只是让你知道技术上存在这么个口子以及为什么不该用它。另外一个实用建议如果你的业务逻辑里对“文件是否变更”很敏感就别用单一时间戳做判断。稳妥的做法是同时看 mtime 和文件内容哈希比如mtime变了就重算一次 sha256哈希没变就认为是误报。这套组合拳在生产环境非常耐用能挡掉绝大多数因为touch、mv、同步工具引起的时间抖动。5. 常见问题与排查技巧实录5.1 备份和同步工具里的时间陷阱rsync是时间问题的高发区几个要点必须记住rsync -a里的-t负责保留 mtime-a已经包含-t。如果只写-r不带-t目标端文件时间全是同步时刻下次同步会认为所有文件都变了全量重传这是最经典的“带宽莫名其妙被吃满”的元凶。rsync不同步 atime几乎所有工具都不同步。原因很朴素读取源文件这个动作本身就在改源文件的 atime同步一个“读取即改变”的字段没有意义。rsync更不同步 ctime目标端的 ctime 必然是落盘那一刻。所以如果监控脚本靠 ctime 判断文件是否被篡改同步之后会全线飘红这时候要把监控规则改成只看 mtime 加内容哈希。cp默认不保留时间要保留用cp -p或cp -a。cp -a等价于-dR --preserveall连链接和权限一起带过去做完整复刻时首选。tar打包默认保留 mtime解包时会恢复。但目录的 mtime 会被后续写入操作改掉因为往目录里写文件本身就在改目录时间所以解包后看到目录时间比文件新是完全正常的不用慌。跨文件系统拷贝会掉精度。ext4 的纳秒时间拷到 NFS 或者 FAT 上可能只剩秒回拷之后纳秒位就没了做严格的时间比对时要把精度截断到秒再比。注意如果发现“文件内容一模一样但每次同步都在重传”先把源和目标的stat拉出来对比 mtime 和大小八成是时间戳没保留或者两个文件系统的精度不一致导致的判断差异。5.2 时间戳漂移、未来时间与时区混乱这类问题的表现形式很迷惑find查出来的文件数量对不上、文件排序奇怪、脚本判断“文件太新”拒绝处理。常见成因有几个。服务器时间被 NTP 校准后跳变尤其是往前跳校正为更早的时间会导致新写入文件的 mtime 比旧文件还早排序全乱。虚拟机快照恢复、容器镜像里打包的时间、从别的机器拷来的文件带着未来时间戳都会造成同样的效果。判断方法很直接$ date -u $ timedatectl $ stat -c %n mtime%y suspicious_file如果文件的 mtime 明显晚于当前时间那就是“未来文件”。用find找它们要小心因为未来的时间会让天数差变成负数-mtime -1这类条件仍然会匹配到容易误伤。想精确找出未来时间的文件可以造一个当前时间的参考文件来比$ touch -d now /tmp/now.ref $ find /data -type f -newer /tmp/now.ref不过touch -d now只有秒级精度亚秒级的未来时间可能漏掉。要求更严就用stat输出时间戳交给awk做数值比较$ now$(date %s) $ find /data -type f -printf %T %p\n | awk -v now$now $1 now {print $2}时区问题同样高频。容器里TZ没设置stat显示的是 UTC 时间人一看就蒙脚本里-newermt用本地时区解释跟日志里的 UTC 时间对不上。我的习惯是在所有时间相关的脚本开头显式设定TZ比对日志和文件时间时统一折算到同一个时区这一条规则帮我省掉了无数次“时间对不上”的排查。5.3 问题速查表现象、原因与处理现象可能原因排查命令处理方式cat之后 atime 没变挂载了 relatime 或 noatimefindmnt -o OPTIONS /需要严格记录时临时 remount strictatimemtime 变了但没人改文件进程写入、日志轮转、同步工具、解包lsof D /data、ausearch结合 ctime 与业务日志定位ctime 频繁变化权限收敛脚本、ACL、SELinux 上下文调整auditctl -w加监控定位到具体进程收敛策略改频率find -mtime 7结果比预期少正负号语义理解偏差同时跑6和7对比数量改用-newermt指定绝对时间touch之后程序仍报文件是新的程序读的是 ctimestat对比三个字段更换判断依据改用 mtime 加哈希归档解包后时间全是解包时刻用了不带-p的cp或归档方式不对对比解包前后stat改用cp -a、tar并保留时间带空格文件名导致批量操作报错未用 NUL 分隔——find -print0 | xargs -0或-exec ... 同步后目标端时间和源端差几分钟文件系统精度差异或时区不一致两端stat对比比对时截断到秒脚本统一TZ6. 把时间戳用到实处三个真实场景6.1 日志清理与保留策略日志目录是时间戳用得最密集的地方。一个能长期稳定跑的清理策略核心就两句话用 mtime 判断“多久没写了”用数量或总量兜底。# 删掉 30 天没写过的日志先看数量 find /var/log/app -type f -name *.log -mtime 30 | wc -l # 确认后执行 find /var/log/app -type f -name *.log -mtime 30 -delete # 兜底单个日志超过 500MB 且今天没写过也清掉 find /var/log/app -type f -name *.log -size 500M -mtime 0 -delete这里为什么用 mtime 而不是 atime因为日志文件基本只写不读atime 没有参考价值而且 relatime 的存在让 atime 本身就不可靠。用 mtime 判断“多久没写过”是语义最贴合的。另外清理脚本一定要配-name限定后缀路径写错了删掉的可能就是别的数据。6.2 增量发布与回滚定位自建发布流程时我常用 mtime 做“本次发布了哪些文件”的依据配合 atime 做访问热度分析# 本次发布窗口内改动的文件清单 find /srv/app -type f -newermt 2024-05-12 09:00:00 -printf %TY-%Tm-%Td %TH:%TM %p\n | sort # 找出发布后 1 小时内被读取过的文件判断哪些文件真的被用上了 find /srv/app -type f -newermt 2024-05-12 09:00:00 -amin -60第二条命令在排查“某个功能上线后没生效”时特别有用如果对应的文件 atime 一直没变说明进程压根没去读它问题可能出在路径映射、缓存或者配置加载顺序上而不是文件内容本身。当然前提是文件系统没关 atime所以这套分析方法在把数据盘设成noatime的机器上不成立——这也是我前面强调“关 atime 之前先想清楚谁在用”的原因。6.3 用时间戳做轻量级变更监控不想上重型监控组件时用stat加定时任务就能做一个够用的文件变更巡检#!/bin/bash # 记录关键配置的 mtime 和 ctime变化就告警 WATCH/etc/nginx/nginx.conf /etc/myapp/config.yml STATE/var/lib/cfgwatch/state for f in $WATCH; do line$(stat -c %n %Y %Z $f) prev$(grep -F $f $STATE 2/dev/null) if [ -n $prev ] [ $prev ! $line ]; then echo 配置发生变化: $line (原: $prev) fi grep -vF $f $STATE 2/dev/null $STATE.tmp; echo $line $STATE.tmp; mv $STATE.tmp $STATE done这套逻辑的好处是同时盯 mtime 和 ctime内容改了 mtime 会变权限或者属主被改了 ctime 会变两种变更都逃不掉。比find -mmin更适合做“发现变化”而不是“列举变化”。我自己在实际操作中的体会是这三个时间戳里最有价值的是 ctime因为它最难被伪造但最容易被忽略的也是它。很多排查卡住并不是因为命令不会用而是因为一开始就选错了参照物——拿 mtime 去回答“有没有人看过这个文件”拿 atime 去回答“这个文件有没有被改过”方向错了后面的命令再多也白搭。养成个习惯看到时间相关的疑问先stat一遍三个时间加创建时间一起看再决定下一步查什么。另外脚本里凡是涉及时间的判断能写绝对时间就不写相对天数能显式指定时区就别依赖环境默认值这两个小习惯能挡掉大部分莫名其妙的时间问题。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →