ls -s什么时候打印“ 0”


13

当然,测试文件是否为空的标准方法是使用test -s FILE,但是我们的一位客户已收到包含以下测试的脚本:

RETVAL=`ls -s ./log/cr_trig.log | awk '{print $1}'`
if test $RETVAL -ne 0
then
    echo "Badness: Log not empty"
    exit 25
fi

供应商声称它可以在他们测试过的两个环境中工作。不用说,它在我测试过的两个地方都严重失败。

所以,我很好奇。什么时候ls -s打印0空文件?

到目前为止,这是我的发现:

  • Linux上的GFS:4
  • Linux上的ext4:0
  • Solaris上的ZFS:1
  • Solaris上的UFS:0
  • AIX上的jfs:0
  • HP-UX上的VxFS:0
  • HP-UX上的HFS:0
  • 在Mac OS X上的HFS:0

我还没有检查过网络文件系统。

问:我如何才能优雅地向其他人解释他们的脚本是错误的

我认为“正确”的版本是:

if test ! -s ./log/cr_trig.log
then
    echo "Badness: Log not empty"
    exit 25
fi

5
只要向他们展示您的测试即可。您拥有证明其测试不可移植的硬数据,您还需要什么?

到目前为止,我在该服务器上看到的最有趣的问题之一。太糟糕了,只能花一分。
ktf

@ktf您可以随时授予赏金。

Answers:


6

非常有趣的发现。尽管我从未使用ls -s过检查文件是否为空的方法,但我会假设它也报告0空文件。

对您的问题:正如Mat已经发表的评论,请向他们显示您的测试结果。为了向他们解释结果,请声明ls -s报告文件系统中已分配块的数量,而不是字节的实际大小。显然,某些文件系统实现分配块,即使它们不必存储任何数据而不是仅在inode中存储NULL指针也是如此。

对此的解释可能与性能有关。创建将保持为空的空文件是正常处理的一个例子(我见过的最常见用法是创建状态文件,其中文件的存在表示软件的某种状态)。

但是通常情况下,创建的文件会很快获得一些数据,因此某个FS的设计人员可能会认为,在文件创建后立即分配一个数据块是值得的,因此,当第一个数据到达时,此任务已经完成。

第二个原因可能是文件过去包含已被擦除的数据。与其释放最后一个数据块,不如保留该数据块供同一文件重用,这可能是值得的。

编辑:

我想到的另一个原因是:您发现值> 0的文件系统是ZFS,RAID + LVM + FS实现和集群文件系统GFS。两者都可能必须存储元数据以维护未存储在inode中的文件完整性。可能是ls -s为该元数据分配的数据块中的计数。


4

与大多数(如果不是全部)其他文件系统不同,ZFS不会预分配inode的静态数组。然后在ZFS上创建一个空文件将使用的新数据块ls -s

我怀疑GFS必须存储导致其他非零结果的同步/锁定数据。


2

ls -s 报告为文件分配的块数,不包括直接存储在目录条目中的块数。

在大多数情况下,块数是字节数除以以字节为单位的块大小,并四舍五入。

块的数量可以少于稀疏文件的数量。例如,在大多数文件系统上,这将创建一个8192字节的文件,跨0个块:

$ perl -e 'truncate STDOUT, 8192' >a
$ ls -l a
-rw-r--r-- 1 gilles gilles 8192 Nov  1 21:32 a
$ ls -s a
0 a

相反,如果文件系统为文件预分配了块或使用块存储元数据,则块的数量可能会更多。考虑到Zfs提供的大量功能及其面向大型文件系统的方向,Zfs在文件大小和块数之间没有明显的对应关系并不令我感到惊讶。我不知道细节,但是块的数量不仅取决于文件的大小,还取决于它的历史记录(如果是截断较大文件的结果,则在一个空文件中可以有多个块)。

解释为什么ls -s是错误的:它不计算文件的大小,而是文件系统相关的数量。首先,这是一种非常间接的方法来确定文件是否为空,这需要外部工具(ls)和一些解析。相反,他们应该使用test -s,而无需解析,并且完全执行请求的内容。如果他们认为这ls -s是测试文件是否为空的好方法,则应由他们承担举证责任,以证明该文件有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.