【问题标题】:Difference between "test -a file" and "test file -ef file"“测试 -a 文件”和“测试文件 -ef 文件”之间的区别
【发布时间】:2012-07-05 21:43:01
【问题描述】:

QNX (Neutrino 6.5.0) 使用 ksh 的开源实现作为其外壳。很多提供的脚本,包括系统启动脚本,都使用了诸如

if ! test /dev/slog -ef /dev/slog; then
    # do something
fi

检查文件系统中是否存在资源管理器。我已经搜索过,只能找到非常枯燥的解释,-ef 检查这两个参数是否实际上是同一个文件。由于指定的文件名相同,因此似乎只是减少了检查文件是否存在。

我已经检查了 test -atest -e 的行为(根据我阅读过的各种文档,它们似乎都在检查任何类型文件的文件是否存在),它们似乎也可以工作。

-ef-a/-e 之间执行的检查有什么区别吗?是否正在使用 -ef 某种尝试来防止文件存在的竞争条件?

【问题讨论】:

  • 似乎确实可以检查文件是否存在两个不同的 stat() 调用。只有在有人检查它的存在时,驱动程序/管理器才会删除 /dev 条目(例如,在关闭之后)?
  • @jhfrontz:我不完全确定你的意思,但(例如)/dev/slog 伪设备只有在驱动程序被杀死时才会被删除,这通常不会在中间发生对test 的调用,因为它是初始系统启动脚本的一部分。在 /dev/slog 的正常情况下,一个进程可以写入设备以记录到文件/控制台/内存,虽然它可能以不同的文件名结束,但 /dev 中暴露的设备应该与之前相同写入 /dev/slog。
  • 我推测 stat'ing 设备有一些副作用(例如,提示驱动程序/经理做一些家务),例如第一个 stat() 调用(来自@987654332 @) 完成后,驱动程序删除/替换文件/设备——从而导致第二个 stat() 获取不同的信息,进而导致 test 失败。我使用 QNX 已经有一段时间了,但the slogger man page 表明与 /dev/slog 交互会产生副作用(例如,取消链接会清除日志)。
  • 我做了更多的挖掘 - test -atest -e 相对较新。在某一时刻,它们似乎不是 QNX 使用的 Posix shell 的一部分(请参阅qnx.com/developers/docs/qnx_4.25_docs/qnx4/utils/s/sh.html。所以我现在怀疑这只是一种遗留模式。
  • @jhfrontz:感谢您的努力,提供最丰富的信息和有用的信息。

标签: ksh qnx


【解决方案1】:

查看 Ubuntu Linux 的 ksh 副本上的 strace 没有发现实质性差异。打一通stat 对比两通。

$ strace test /tmp/tmp.geLaoPkXXC -ef /tmp/tmp.geLaoPkXXC

显示了这个:

mmap(NULL, 7220736, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f11dc80b000
close(3)                                = 0
stat("/tmp/tmp.geLaoPkXXC", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
stat("/tmp/tmp.geLaoPkXXC", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
close(1)                                = 0
close(2)                                = 0

...而

$  strace test -a /tmp/tmp.geLaoPkXXC

显示了这个:

fstat(3, {st_mode=S_IFREG|0644, st_size=7220736, ...}) = 0
mmap(NULL, 7220736, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6b49e2b000
close(3)                                = 0
stat("/tmp/tmp.geLaoPkXXC", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
close(1)                                = 0
close(2)                                = 0

一个stat vs 两个。

$ ksh --version
  version         sh (AT&T Research) 93u 2011-02-08

【讨论】:

    【解决方案2】:

    我们不知道代码如何使用stat没有代码,我们需要通过代码找到差异。

    /* code for -ef */
    return (stat (argv[op - 1], &stat_buf) == 0
                      && stat (argv[op + 1], &stat_spare) == 0
                      && stat_buf.st_dev == stat_spare.st_dev
                      && stat_buf.st_ino == stat_spare.st_ino);
    
    
    /* code for -e/-a */
        case 'a':                   /* file exists in the file system? */
        case 'e':
          return stat (argv[pos - 1], &stat_buf) == 0;
    

    所以,如果名称相同并且两个同名的 stat() 将返回相同的值,那么, test -a/-e filetest file -ef file 相同。我们知道第一个条件为真,从@tinman 的 cmets 中我们知道第二个条件也为真

    【讨论】:

      猜你喜欢
      • 2018-07-27
      • 1970-01-01
      • 2013-11-07
      • 2011-08-19
      • 1970-01-01
      • 1970-01-01
      • 2012-02-17
      • 2017-11-08
      • 2011-07-15
      相关资源
      最近更新 更多