du对同一个文件给出两个不同的结果


23

我是计算机化学专业的研究生,可以访问Linux群集。群集由一个非常大的文件服务器(25 TB)组成,数十个计算节点连接到该服务器。每个计算节点由8至24个Intel Xeon内核组成。每个计算节点还包含大约365 TB的本地磁盘。

由于该文件服务器通常由研究组中的十几个用户访问,因此该文件服务器主要用于长期文件存储(每晚备份一次,而从不备份计算节点的本地磁盘)。因此,系统管理员已指示我们在本地磁盘上运行模拟(这些I / O比文件服务器具有更快的I / O),以便不降低其他用户使用文件服务器的速度。

因此,我在本地磁盘上运行模拟,然后在完成后将轨迹文件(正在运行分子动力学(MD)模拟)复制到文件服务器进行存储。假设我有一个traj.trr在节点本地磁盘上的目录中调用的轨迹文件/home/myusername/mysimulation1/traj.trr。对于长期存储,我总是将traj.trr文件复制到文件服务器中的目录~/mysimulation1/traj.trr,其中~代表文件服务器中的目录/export/home/myusername。复制后,我习惯性地使用du -h来验证/home/myusername/mysimulation1/traj.trr文件大小是否与相同~/mysimulation1/traj.trr。这样,我至少可以合理地确定向文件服务器的传输已成功。例如:

cd /home/myusername/mysimulation1/
cp -v traj.trr ~/mysimulation1/
du /home/myusername/mysimulation1/traj.trr -h
du ~/mysimulation1/traj.trr -h

如果两个调用du -h给出相同的可读文件大小,则可以合理地确定传输/复制成功。(traj.trr根据我运行的确切模拟,我的典型文件的大小范围约为15到20 GB。)如果我在两个文件上运行du(即,不进行-h切换)traj.trr,它们的字节大小通常非常非常相似- -通常在几个字节之内。在过去的一年半中,我一直在使用这种总体方法,没有任何问题。

但是,最近我遇到了以下问题:有时du -h报告两个traj.trr文件的大小相差数GB。这是一个例子:

cd /home/myusername/mysimulation1/            # this is the local disk
cp -v traj.trr ~/mysimulation1/
du traj.trr -h
cd ~/mysimulation1/                           # this is the fileserver
du traj.trr -h

来自两个调用to的输出du -h分别如下:

20G     traj.trr
28G     traj.trr

我相信前者(即traj.trr本地磁盘中的/home/myusername/mysimulation1/)是正确的文件大小,因为我的模拟轨迹预计每个约为15至20 GB。但是,实际上文件服务器上的文件又怎么可能更大呢?如果cp传输失败,我可以看到它会变得更小。但是我不知道它可能会更大

当我执行与上述相同的命令时,会得到类似的输出,但是没有-h切换到du

20717480        traj.trr
28666688        traj.trr

您能想到造成这种差异的任何原因吗?

如果以某种不太可能的机会出现du故障,我可以接受。但我只需要确保traj.trr文件服务器上的副本完整且与本地磁盘上的源版本相同即可。我需要删除本地文件,以便有足够的本地磁盘空间来运行新的模拟,但是我不能承受traj.trr文件服务器上的版本损坏的负担。

所述.trr文件格式(从的Gromacs分子动力学封装)是二进制格式,而不是文本。因此,我不确定文件是否可以通过程序可靠地比较diff


5
尝试运行md5sumsha1sum处理文件。他们匹配吗?
cjm 2013年

2
@cjm我只是md5sum在两个文件上运行。两个校验和匹配。所以我想这意味着两个文件是相同的?
安德鲁

3
报告什么尺寸ls -l?该命令du报告磁盘上有多少空间用于文件,而不是文件的大小。磁盘上的大小可能受文件系统及其分配策略的影响。
casey 2013年

2
@casey ls -l -h表示两个文件均为20 GB。同样,ls -l说两个文件都是21214683940字节。因此,我猜这些文件的大小是相同的,但是不要使用相同数量的磁盘空间(根据du)。
安德鲁

2
@Andrew给出的ls报告的大小是相同的,并且散列是相同的,您可以得出结论文件是相同的。这些工具使您有所需的信心,并向您证明du并不是满足您需求的工具。
casey 2013年

Answers:


32

您确实应该使用类似md5sumsha1sum检查完整性的方法。

如果您确实要使用大小,请使用ls -ldu -b

du实用程序通常仅显示文件的磁盘使用情况,即文件使用了多少文件系统。该值完全取决于备份文件系统和其他因素,例如稀疏文件。

例:

$ truncate -s 512M foo
$ cat foo >bar
$ ls -l foo bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:06 bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:03 foo
$ du foo bar
0       foo
524288  bar
$ du -b foo bar
536870912       foo
536870912       bar

我们有两个文件都包含512MB的零。第一个存储稀疏,不使用任何磁盘空间,而第二个显式存储每个字节在磁盘上。-相同的文件,但磁盘使用情况完全不同。

-b选项可能对您有利:

   -b, --bytes
          equivalent to '--apparent-size --block-size=1'

   --apparent-size
          print apparent sizes, rather than disk usage; although the apparent
          size is  usually  smaller,  it  may  be  larger  due  to  holes  in
          ('sparse')  files, internal fragmentation, indirect blocks, and the
          like

8

当您将相同的数据放在2个不同的HDD上时,这是一个常见的问题。您将希望du使用带有和附加开关的命令来运行该命令,并假设它具有命令-应该在这些是Linux节点的情况下使用它。

开关?

   --apparent-size
          print  apparent  sizes,  rather  than  disk  usage;  although the 
          apparent size is usually smaller, it may be larger due to holes in
          ('sparse') files, internal fragmentation, indirect blocks, and the 
          like

$ du -sh --apparent-size /home/sam/scsconfig.log ~/scsconfig.log 
93K /home/sam/scsconfig.log
93K /root/scsconfig.log

上面的文件系统是一个本地磁盘(/root),另一个/home/sam是我NAS中的NFS共享。

$ df -h . /home/sam
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
                      222G  118G   92G  57% /
mulder:/export/raid1/home/sam
                      917G  566G  305G  65% /home/sam

那么这是什么一回事?

这使很多人感到困惑,但请记住,将文件存储到磁盘时,即使它们仅使用了一部分,也会占用空间块。当您du不运行时,将--apparent-size根据使用的磁盘块空间量而不是文件消耗的实际空间来获取大小。

改用校验和?

如果您担心比较两个文件树,则这可能是一个更好的选择。您可以使用此命令来计算所有文件的校验和,然后计算校验和的最终校验和。此示例使用了,sha1sum但是您可以轻松地使用它md5sum

$ cd /some/dir
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum

$ cd ~/dir1
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

$ cd ~/dir2
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

因此,我们可以看到2棵树是相同的。

(注意:find命令将列出文件在文件系统中显示的文件。因此,如果要比较来自不同文件系统的两个目录(例如Ext3与APFS),则需要在最后的sha1sum之前首先进行排序。董宪军


5

简短的答案:不要测试文件大小,请测试命令的返回状态。返回状态是复制是否成功的唯一可靠指示(不直接将两个文件逐个字节地进行间接比较,如果复制成功,则是多余的)。

检查文件大小不是检查复制是否成功的非常有用的方法。在某些情况下,这可能是一个有用的完整性检查,例如,当您从Web下载文件时。但是这里有一个更好的方法。

所有Unix命令都返回一个状态以指示它们是否成功:0表示成功,1表示错误。因此,请检查的退出状态cpcp如果失败,通常会打印一条错误消息,指出错误是什么。在脚本中,最后一个命令的退出状态在magic变量中$?

cp -v traj.trr ~/mysimulation1/
if [ $? -ne 0 ]; then
  echo 1>&2 "cp failed due to the error above"
  exit 2
 fi

$?您可以使用布尔运算符而不是检查是否为零。

cp -v traj.trr ~/mysimulation1/ || exit 2

如果您正在运行脚本,并且希望在任何命令失败时停止脚本,请运行set -e。如果任何命令失败(即返回非零状态),脚本将立即以与命令相同的状态退出。

set -e
…
cp -v traj.trr ~/mysimulation1/

至于原因您复制的文件是较大的,那一定是因为它是一个稀疏文件。稀疏文件是压缩的一种粗略形式,其中不存储仅包含空字节的块。复制文件时,该cp命令读取和写入空字节,因此在原始文件缺少块的情况下,副本中的块充满了空字节。在Linux下,该cp命令尝试检测稀疏文件,但它并不总是成功。cp --sparse=always使其付出更大的努力,但会占用很少的CPU时间。

更一般而言,du由于其他形式的压缩,可能会返回不同的结果。但是,压缩文件系统很少见。如果要以文件的字节数(而不是文件使用的磁盘块数)来了解文件的大小,请使用ls -l代替du


非常感谢!您是否知道是否有一个(单独的)实用程序可以告诉我我的文件是否稀疏?
安德鲁

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.