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

Mat*_*nco 13 ls filesystems compatibility shell-script

当然,测试文件是否为空的标准方法是使用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
Run Code Online (Sandbox Code Playgroud)

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

所以,我很好奇。什么时候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
Run Code Online (Sandbox Code Playgroud)

ktf*_*ktf 6

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

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

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

但是通常创建的文件很快就会得到一些数据,所以某个FS的设计者可能认为在文件创建时立即分配一个数据块是值得的,所以当第一个数据到达时,这个任务已经完成。

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

编辑:

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