我是计算化学的研究生,可以访问 Linux 集群。该集群由一个非常大 (25 TB) 的文件服务器组成,其中连接了几十个计算节点。每个计算节点由 8 到 24 个英特尔至强内核组成。每个计算节点还包含一个大约 365 TB 的本地磁盘。
由于研究组的十几个用户经常访问文件服务器,文件服务器主要用于长期文件存储(每晚备份,而计算节点的本地磁盘从不备份)。因此,系统管理员指示我们在本地磁盘上运行模拟——它们的 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
Run Code Online (Sandbox Code Playgroud)
如果这两个调用du -h
给出相同的人类可读文件大小,那么我可以合理地确定传输/复制成功。(我的典型traj.trr
文件大小从大约 15 GB 到 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
Run Code Online (Sandbox Code Playgroud)
两次调用的输出du -h
分别如下:
20G traj.trr
28G traj.trr
Run Code Online (Sandbox Code Playgroud)
我相信前者(即traj.trr
本地磁盘中的/home/myusername/mysimulation1/
)是正确的文件大小,因为我的模拟轨迹预计每个约为 15 到 20 GB。但是文件服务器上的文件怎么会更大呢?如果cp
传输失败,我可以看到它会更小。但我不明白它实际上如何更大。
当我执行与上面相同的命令时,我得到了类似的输出,但没有给-h
开关du
:
20717480 traj.trr
28666688 traj.trr
Run Code Online (Sandbox Code Playgroud)
你能想出任何不同的原因吗?
如果由于某种不太可能的机会出现du
某种故障,我可以接受。但我真的需要确保traj.trr
文件服务器上的副本完整且与本地磁盘上的源版本相同。我需要删除本地文件,以便我有足够的本地磁盘空间来运行新的模拟,但我无法承受traj.trr
文件服务器上的的版本损坏。
所述.trr文件格式(从的Gromacs分子动力学封装)是二进制格式,而不是文本。因此,我不确定这些文件是否可以通过诸如diff
.
mic*_*has 37
你真的应该使用类似md5sum
或sha1sum
检查完整性的东西。
如果您真的想使用大小,请使用ls -l
或du -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
Run Code Online (Sandbox Code Playgroud)
我们有两个文件都包含 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
Run Code Online (Sandbox Code Playgroud)
当您将相同的数据放在 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
Run Code Online (Sandbox Code Playgroud)
$ du -sh --apparent-size /home/sam/scsconfig.log ~/scsconfig.log
93K /home/sam/scsconfig.log
93K /root/scsconfig.log
Run Code Online (Sandbox Code Playgroud)
上面的文件系统是一个本地磁盘 ( /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
Run Code Online (Sandbox Code Playgroud)
这让很多人感到困惑,但请记住,当文件存储到磁盘时,它们会消耗空间块,即使它们只使用这些块的一部分。当您在du
没有 的情况下运行时,--apparent-size
您将根据使用的磁盘块空间量获得大小,而不是文件消耗的实际空间。
如果您担心比较 2 个文件树,这可能是一个更好的选择。您可以使用此命令计算所有文件的校验和,然后计算校验和的最终校验和。这个例子使用了,sha1sum
但你也可以很容易地使用它md5sum
。
$ cd /some/dir
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
Run Code Online (Sandbox Code Playgroud)
$ cd ~/dir1
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911 -
$ cd ~/dir2
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911 -
Run Code Online (Sandbox Code Playgroud)
所以我们可以看到两棵树是相同的。
(注意:find 命令将列出文件系统中出现的文件。因此,如果您正在比较来自不同文件系统的两个目录(例如 Ext3 与 APFS),您需要在最终 sha1sum 之前先排序。(由董贤君)
简短的回答:不要测试文件大小,测试命令的返回状态。返回状态是复制是否成功的唯一可靠指示(缺少逐字节比较两个文件,直接或间接 - 如果复制成功,这是多余的)。
检查文件大小并不是检查复制是否成功的非常有用的方法。在某些情况下,它可能是一种有用的完整性检查,例如当您从 Web 下载文件时。但这里有更好的方法。
所有 Unix 命令都会返回一个状态来指示它们是否成功:0 表示成功,1 或更多表示错误。因此,请检查 的退出状态cp
。cp
如果失败,通常会打印一条错误消息,指出错误是什么。在脚本中,最后一个命令的退出状态在魔法变量中$?
。
cp -v traj.trr ~/mysimulation1/
if [ $? -ne 0 ]; then
echo 1>&2 "cp failed due to the error above"
exit 2
fi
Run Code Online (Sandbox Code Playgroud)
$?
您可以使用布尔运算符,而不是检查是否为零。
cp -v traj.trr ~/mysimulation1/ || exit 2
Run Code Online (Sandbox Code Playgroud)
如果您正在运行脚本并希望脚本在任何命令失败时停止,请运行set -e
. 如果任何命令失败(即返回非零状态),脚本将立即以与命令相同的状态退出。
set -e
…
cp -v traj.trr ~/mysimulation1/
Run Code Online (Sandbox Code Playgroud)
至于你复制的文件较大的原因,一定是因为它是一个稀疏文件。稀疏文件是一种粗略的压缩形式,其中不存储仅包含空字节的块。当您复制文件时,该cp
命令会读取和写入空字节,因此在原始文件丢失块的地方,副本的块充满了空字节。在 Linux 下,该cp
命令尝试检测稀疏文件,但并不总是成功;cp --sparse=always
使其更加努力,但代价是 CPU 时间略有增加。
更一般地说,du
由于其他形式的压缩,可能会返回不同的结果。不过,压缩文件系统很少见。如果您想通过文件中的字节数了解文件的大小,ls -l
而不是它使用的磁盘块数,请使用du
.