在Perl的各种文件测试运算符中,最有用的运算符之一就是 -C 了。 它返回的是文件的ctime到程序启动的那一时刻经过的天数。 如果不是整数天,返回值就带有小数。
这个运算符经常用来检测文件是否过期,比如判断文件距离上次修改是否超过了3天, 如果超过就将其删除。但是,你是否真正理解 -C 的工作原理呢?
何谓ctime
要想理解-C,就必须理解什么是ctime。我们知道文件测试运算符的返回值都是stat系统调用的结果, 因此从stat的文档中就可以找到答案:
$ man 2 stat
...
The field st_ctime is changed by writing or by setting inode information
(i.e., owner, group, link count, mode, etc.).
可见,ctime是inode的更新时间,因此不仅是改变文件内容,移动文件、修改所有者等操作都会改变ctime。 这篇文章 说得更详细:
文件的 Change time,ctime 是在写入文件、更改所有者、权限或链接设置时
随 Inode 的内容更改而更改的。只要stat出来的内容发生改变就会发生改变。
mtime的改变必然导致ctime的改变。
-C的值如何计算?
perl的文档中对-C是这样说明的:
$ perldoc -f -X
...
-M Script start time minus file modification time, in days.
-A Same for access time.
-C Same for inode change time (Unix, may differ for other platforms)
也就是说,-C 是脚本执行开始那一刻距离文件的ctime之间的天数。 用计算式来表述,可以这样写:
(($^T - ((stat($filename))[10])) / 86400)
$^T是Perl开始执行时的时间戳。
因此,在同一个程序中两次执行 -C 的结果是一样的。 所以,下面这个程序得到的是相同的结果:
print -C "foo.bar";
sleep 10;
print -C "foo.bar";
同样,在mod_perl环境下,只要服务器没有重启,那么任何时候执行-C得到的结果都相同。
(实际上上面这句话并不严密,因为httpd会同时启动数个进程,而多个进程的$^T并不一定相同,从而-C的结果也有可能不同。 另外,一般情况下httpd进程在处理完一定的请求之后,进程会结束并启动一个新进程,也会使得$^T重置,影响-C的结果。)
那么,如何获得执行 那一刻距离ctime的天数呢? 有了上面的公式,不难得出,应该这样计算:
(-C $filename) + (time() - $^T) / 86400