更新:原来我非常愚蠢。我正在检查修改时间,我应该检查访问时间。它不可重复的原因是测试文件是用dd if=/dev/urandom of="$target" bs='1K' count=1 || exit 1
制作的,大部分时间对于新文件的修改时间(dd
的结尾)来说太快了,不同于访问时间(dd
的开始时间)。另外需要注意的事项。
我正在编写一个脚本,将一个文件的访问时间加上两年的时间应用到另一个文件中。这使用stat -c %x
,date --rfc-3339=ns
和touch -a --date="$result"
。 stat
和date
两个输出日期字符串均为纳秒,如
2012-11-17 10:22:15.390351800+01:00
,info coreutils 'touch invocation'
表示它支持纳秒。但有时候在应用触摸时,应用的时间戳与之后返回的时间戳之间存在细微差别。这是来自实际运行的数据:
$ for i in {1..100}; do ./t_timecopy.sh 2>/dev/null| grep ASSERT; done
ASSERT:Expecting same access time expected:<2012-11-17 10:58:40.719320935+01:00> but was:<2012-11-17 10:58:40.723322203+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:00:04.342346275+01:00> but was:<2012-11-17 11:00:04.346358718+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:00:39.343348183+01:00> but was:<2012-11-17 11:00:39.347351686+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:01:08.655348312+01:00> but was:<2012-11-17 11:01:08.659347625+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:01:37.930346876+01:00> but was:<2012-11-17 11:01:37.934347311+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:02:16.939319832+01:00> but was:<2012-11-17 11:02:16.943323061+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:02:46.456443149+01:00> but was:<2012-11-17 11:02:46.458379114+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:03:15.487339595+01:00> but was:<2012-11-17 11:03:15.491341426+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:04:04.646335863+01:00> but was:<2012-11-17 11:04:04.650346634+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:04:14.410326608+01:00> but was:<2012-11-17 11:04:14.414331233+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:04:24.159367348+01:00> but was:<2012-11-17 11:04:24.163352418+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:04:33.931387953+01:00> but was:<2012-11-17 11:04:33.935350115+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:05:03.394361030+01:00> but was:<2012-11-17 11:05:03.398320957+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:05:42.054317430+01:00> but was:<2012-11-17 11:05:42.059106497+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:06:40.346320820+01:00> but was:<2012-11-17 11:06:40.350346956+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:08:17.194346778+01:00> but was:<2012-11-17 11:08:17.198338832+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:08:27.102347603+01:00> but was:<2012-11-17 11:08:27.106320380+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:09:16.247322948+01:00> but was:<2012-11-17 11:09:16.251347966+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:09:55.191325266+01:00> but was:<2012-11-17 11:09:55.195320672+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:12:09.915318301+01:00> but was:<2012-11-17 11:12:09.919334099+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:12:28.906346914+01:00> but was:<2012-11-17 11:12:28.910348186+01:00>
因此,100个测试中有21个失败,平均值为3.938毫秒,中位数为4.001毫秒。有什么想法会导致这种情况吗?
$ uname -a
Linux user 2.6.32-22-generic #33-Ubuntu SMP Wed Apr 28 13:27:30 UTC 2010 i686 GNU/Linux
答案 0 :(得分:0)
我使用了一堆(公认的快速和肮脏)oneliners在我的系统上测试你的问题 - 一个Mandriva Linux 2010.1(x86-64):
seq 1 1000 | while read f; do sleep 0.01; touch test-$f-0; done
seq 1 1000 | while read f; do touch -a -d "$(stat -c %x test-$f-0 | sed 's|^2010|2012|')" test-$f-1; done
seq 1 1000 | while read f; do A="$(stat -c %x test-$f-0)"; B="$(stat -c %x test-$f-1)"; if [[ ! "${A#2010}" = "${B#2012}" ]]; then echo test-$f; fi; done
我甚至无法重现您的问题。听起来,触摸不是在-d参数的预期时间戳中提供的,而是以其他方式计算出来的。
当然问题可能是系统特定的,在这种情况下,我们需要有关系统的更多信息(CPU,OS 32或64位,内核/ glibc / coreutils版本等)。
更新:
我尝试使用32位版本的stat和touch。没有问题出现。内核仍然是64位的。
UPDATE2:
我也尝试过这套oneliner,更专注于atime:
$ seq 1 1000 | while read f; do sleep 0.01; touch test-$f-0; done
$ seq 1 1000 | while read f; do sleep 0.01; touch test-$f-1; done
$ seq 1 1000 | while read f; do sleep 0.01; cat test-$f-0; done
$ seq 1 1000 | while read f; do touch -a -d "$(stat -c %x test-$f-0 | sed 's|^2010|2012|')" test-$f-1; done
$ seq 1 1000 | while read f; do A="$(stat -c %x test-$f-0)"; B="$(stat -c %x test-$f-1)"; if [[ ! "${A#2010}" = "${B#2012}" ]]; then echo test-$f; fi; done
再次检测不到问题。我试用了relatime和strictatime挂载选项。
UPDATE3:
我只需要在我的Mandriva i686笔记本电脑上执行上述测试。我似乎也没有纳秒精度的问题。我还在另一个32位系统上验证,如果不支持纳秒精度(例如在ext3上),则stat输出中的纳秒字段变为零。
答案 1 :(得分:0)
触摸Windows 7 64位带来了类似的问题。这是我的漏洞利用代码:
touch a && touch b && ls --full-time a b
touch -r a b && ls --full-time a b
输出:
-rw-rw-rw- 1 Jarek 0 0 2012-05-09 12:05:27.851839700 +0200 a
-rw-rw-rw- 1 Jarek 0 0 2012-05-09 12:05:27.874841000 +0200 b
-rw-rw-rw- 1 Jarek 0 0 2012-05-09 12:05:27.851839700 +0200 a
-rw-rw-rw- 1 Jarek 0 0 2012-05-09 12:05:27.851839000 +0200 b
ls
和touch
来自gnuwin32。在前2个输出行中,存在20ms的时间戳差异。好。但是在第二轮比赛中他们应该是平等的(b
从a
获得了印记。没运气。差异为0.7 us :)。
svn status
看到了差异,因此很难用touch
来欺骗它。