Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux文件创建时间戳竞争条件_Linux_Find_Timestamp - Fatal编程技术网

Linux文件创建时间戳竞争条件

Linux文件创建时间戳竞争条件,linux,find,timestamp,Linux,Find,Timestamp,我正在尝试在Linux下做一件我认为很简单的事情。我有一个运行各种测试程序的bash脚本,我想确定当前目录中的哪些文件是由测试程序创建的。所以我在做这样的事情: touch timestamp-file run the test find -newer timestamp-file -type f > list-of-files rm -f timestamp-file 触摸时间戳文件 运行测试 查找-更新的时间戳文件-类型f>文件列表 rm-f时间戳文件 事实证明find-newer的粒度很差

我正在尝试在Linux下做一件我认为很简单的事情。我有一个运行各种测试程序的bash脚本,我想确定当前目录中的哪些文件是由测试程序创建的。所以我在做这样的事情:

touch timestamp-file run the test find -newer timestamp-file -type f > list-of-files rm -f timestamp-file 触摸时间戳文件 运行测试 查找-更新的时间戳文件-类型f>文件列表 rm-f时间戳文件 事实证明find-newer的粒度很差,因此通常情况下,测试程序生成的一些文件显示为比时间戳文件旧。于是我尝试了这个:

ls -tr1 | sed '1,/timestamp-file/d' ls-tr1 | sed'1,/timestamp file/d' 生成相同的列表。这通常有效,但并不总是有效。我仍然会遇到这样的情况:测试生成的文件显示为比时间戳文件旧

谢谢


另外,我可以通过另一种方式来完成这一点,即在测试程序运行之前和之后,分别拍摄目录的两个快照,并对它们进行比较。第二个列表中不在第一个列表中的任何文件都必须是由测试程序创建的(我不关心后台作业或其他用户写入目录)。但是这个方法不是我想要的,因为如果在运行测试之前没有删除输出文件(应该是,但在某些情况下可能不是),此方法会说它不是由测试程序创建的,因为在运行测试程序之前它在目录中。

您实际上可以使用touch强制将目录中所有当前文件的时间戳设置为远过去,例如:

touch -t 200801010000.00 *
如果在运行测试之前执行此操作,则时间差应该足以让“
find-newer
”拾取它。如果粒度为2分钟,则可以将所有当前文件设置为10分钟前,将时间戳文件设置为5分钟前,然后运行测试

因此,您的脚本变成:

touch -t (current time - 10 minutes) *
touch -t (current time -  5 minutes) timestamp-file
run the test
find -newer timestamp-file -type f > list-of-files
rm -f timestamp-file
假设您有一个像样的Perl安装,您可以在5分钟前(或使用-600表示10分钟)以正确的格式为“
date-t
”执行以下操作:

如果出于某种原因,不允许您更改时间戳,请使用:

sleep 300
touch timestamp-file
sleep 300
run the test
find -newer timestamp-file -type f > list-of-files
rm -f timestamp-file

这也有同样的效果,但是给你十分钟的时间去喝杯咖啡(或者如果你不是一个喝咖啡的人,你选择的毒药)。

为什么不创建一个临时目录来运行测试呢?在目录上使用基于时间戳的名称来帮助跟踪何时发生的结果,并在完成时删除整个目录。

在运行之前获取所有文件的文件名,但包括它们的时间戳:

find -printf '%p %T@\n' | sort > file1
如果您没有可用的“查找”选项,您也可以使用stat进行该作业:

find -print0 | xargs -0 stat -c "%n %Y" | sort > file1

运行到
文件2
之后。然后使用

comm -1 -3 file1 file2
它将向您显示
file2
特有的行,如果我没有弄错的话,这些行必须是新文件。如果它们以前存在过,它们的修改时间将发生变化,这由
%T@
thingy(打印自1970年以来的秒数)负责:

[js@HOST2cpp]$find-printf“%p%T@\n”| sort>file1 [js@HOST2cpp]$echo foo>bar [js@HOST2cpp]$echo foo>baz [js@HOST2cpp]$find-printf“%p%T@\n”| sort>file2 [js@HOST2cpp]$comm-1-3文件1文件2 . 1230947309.0000000000 /bar 1230947308.0000000000 /巴兹12309473090000000000 /文件2 1230947315.0000000000 [js@HOST2cpp]$find-printf“%p%T@\n”| sort>file1 [js@HOST2cpp]$echo lol>条 [js@HOST2cpp]$find-printf“%p%T@\n”| sort>file2 [js@HOST2cpp]$comm-1-3文件1文件2 /bar 1230947359.0000000000 /文件1230947362.0000000000 [js@HOST2[cpp]$`

如果您考虑如何实现<代码>查找(1),那么将清楚为什么这有时可能不像您预期的那样工作。这里有一个提示:

  $ touch timestamp ; touch newer ; find . -newer timestamp 
  $ rm timestamp newer
  $ touch timestamp ; sleep 1 ; touch newer ; find . -newer timestamp
  .
  ./newer
  $
find(1)
使用系统调用
stat(2)
获取文件mtime/ctime/atime值。以下是来自
(Linux)的
struct stat
的元素:


在Linux上(通常是unices)
time\u t
是一个整数,表示“从1970年开始的秒数”。因此,
-更新的
所能理解的最美好的格言只有一秒钟。

谢谢……这是一个合理的建议。问题是,对于dir中会找到哪些文件,有几种预期,并且每个测试可能会有所不同。因此,我不知道需要将哪些输入文件复制到temp dir。我会再考虑一下……时间戳粒度是出了名的非标准。只是:mkdir-tmp(cd-tmp#reference files in..而不是..rm-Rf-tmp实际上,在触摸工作后只需将usleep 500000放入,但这看起来很笨拙。整个套件需要很长时间,因此添加此类延迟是有问题的。大多数测试需要10-60秒。跑,所以没有比赛条件。但是一个测试只需要几分之一秒就会产生问题。你的第一个解决方案是令人信服的。更改时间戳没有真正的问题,因此我可以按照您所描述的那样设置它们。触球太差-t不需要“1970年以来的秒数”作为参数。(=@Dave,假设您安装了Perl,CPAN中的Date::Manip应该可以很容易地将UNIX时间戳转换为字符串和字符串。这太棒了。我原以为解决方案是将我的两种方法结合起来,但我会使用笨拙的“ls-l”,我完全忘记了comm(我从来没有这么熟悉过它,但我现在很熟悉)。谢谢!事实证明find在Darwin(Mac OS)上不能这样工作,所以我重新使用ls-l,因为我需要它在许多平台上工作,但你的解决方案对我来说仍然是最好的。谢谢!Dave Wade Stein,你也可以使用stat而不是find。find-print0 | xargs-0 stat-c“%n%Y”.也许有空? [js@HOST2 cpp]$ find -printf '%p %T@\n' | sort > file1 [js@HOST2 cpp]$ echo foo>bar [js@HOST2 cpp]$ echo foo>baz [js@HOST2 cpp]$ find -printf '%p %T@\n' | sort > file2 [js@HOST2 cpp]$ comm -1 -3 file1 file2 . 1230947309.0000000000 ./bar 1230947308.0000000000 ./baz 1230947309.0000000000 ./file2 1230947315.0000000000 [js@HOST2 cpp]$ find -printf '%p %T@\n' | sort > file1 [js@HOST2 cpp]$ echo lol>bar [js@HOST2 cpp]$ find -printf '%p %T@\n' | sort > file2 [js@HOST2 cpp]$ comm -1 -3 file1 file2 ./bar 1230947359.0000000000 ./file2 1230947362.0000000000 [js@HOST2 cpp]$`
  $ touch timestamp ; touch newer ; find . -newer timestamp 
  $ rm timestamp newer
  $ touch timestamp ; sleep 1 ; touch newer ; find . -newer timestamp
  .
  ./newer
  $
  time_t    st_atime;   /* time of last access */
  time_t    st_mtime;   /* time of last modification */
  time_t    st_ctime;   /* time of last status change */