duは同じファイルに対して2つの異なる結果を与えます


23

私は、Linuxクラスターにアクセスできる計算化学の大学院生です。クラスターは非常に大きな(25 TB)ファイルサーバーで構成されており、数十の計算ノードが接続されています。各計算ノードは、8〜24個のIntel Xeonコアで構成されています。各計算ノードには、約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

2つの呼び出しでdu -h人間が読み取れるファイルサイズが同じである場合、転送/コピーが成功したことは合理的に確信できます。(私の典型的なtraj.trrファイルは、実行した正確なシミュレーションに応じて、サイズが約15〜20 GBの範囲です。)2つのファイルでdu-hスイッチなしで)実行した場合、traj.trr通常、バイト単位のサイズは非常に似ています- -通常、わずか数バイト以内。過去1年半、この全体的な方法を問題なく使用しています。

ただし、最近、次の問題にdu -h遭遇しました。2つの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

への2つの呼び出しからの出力du -hは、それぞれ次のとおりです。

20G     traj.trr
28G     traj.trr

私のシミュレーションの軌跡はそれぞれ約15〜20 GBであると予想されるため、前者(つまり、traj.trrローカルディスク内/home/myusername/mysimulation1/)が正しいファイルサイズであると考えています。しかし、ファイルサーバー上のファイルは実際にはどのように大きくできますか?どういうわけかcp転送が失敗した場合、それがどのように小さくなるかを見ることができました。しかし、実際にどのように大きくなるかはわかりません。

上記と同じコマンドを実行すると、同様の出力が得られますが、-hスイッチは指定されていませんdu

20717480        traj.trr
28666688        traj.trr

違いの理由を考えることができますか?

万が一、du何らかの形で誤動作している場合は、大丈夫です。ただしtraj.trr、ファイルサーバー上ののコピーが完全であり、ローカルディスク上のソースバージョンと同一であることを確認する必要があります。新しいシミュレーションを実行するのに十分なローカルディスク領域を確保するためにローカルファイルを削除する必要がありますがtraj.trr、ファイルサーバー上のバージョンを破損させることはできません。

(Gromacs分子動力学パッケージからの).trrファイル形式は、テキストではなくバイナリ形式です。したがって、などのプログラムでファイルを確実に比較できるかどうかはわかりませんdiff


5
md5sumまたは実行してみてくださいsha1sum。彼らは一致しますか?
cjm

2
@cjm md5sum2つのファイルを実行しました。2つのチェックサムが一致します。だから、これは2つのファイルが同じであることを意味すると思いますか?
アンドリュー

3
どのサイズが報告されls -lますか?このコマンドduは、ファイルの大きさではなく、ディスク上のディスクの空き容量を報告します。ディスク上のサイズは、ファイルシステムとその割り当て戦略によって影響を受ける可能性があります。
ケーシー

2
@casey ls -l -hは、両方のファイルが20 GBであると言います。同様に、ls -l両方のファイルが21214683940バイトであると言います。したがって、ファイルは同じサイズであると思いますが、同じ量のディスク容量を使用しないでください(によるdu)。
アンドリュー

2
lsによって報告されるサイズが同じであり、ハッシュが同じである場合、@ Andrewはファイルが同じであると結論付けることができます。これらのツールは、あなたに必要な自信を与え、duがあなたのニーズを満たすツールではないことを示します。
ケーシー

回答:


32

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

512MBのゼロを含む2つのファイルがあります。1つ目はまばらに保存され、ディスク領域を使用しませんが、2つ目は各バイトをディスクに明示的に保存します。-同じファイルですが、ディスク使用量が完全に異なります。

この-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すると、ファイルによって消費される実際のスペースではなく、使用されているディスクのブロックスペースの量に基づいてサイズが取得されます。

代わりにチェックサムを使用していますか?

ファイルの2つのツリーを比較することに関心がある場合、これはおそらくより良いオプションです。このコマンドを使用して、すべてのファイルのチェックサムを計算し、チェックサムの最終チェックサムを計算できます。この例ではを使用して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など)の2つのディレクトリを比較する場合、最後のsha1sumの前に最初にソートする必要があります。 Xianjun Dong)


5

簡単な答え:ファイルサイズをテストせず、コマンドのリターンステータスをテストします。戻りステータスは、コピーが成功したかどうかの唯一の信頼できる指標です(2つのファイルを直接または間接的にバイト単位で比較すること以外-コピーが成功した場合は冗長です)。

ファイルサイズの確認は、コピーが成功したかどうかを確認するための非常に有用な方法ではありません。場合によっては、たとえばWebからファイルをダウンロードするときなど、有用な健全性チェックになります。しかし、ここにはもっと良い方法があります。

すべてのUnixコマンドは、成功したかどうかを示すステータスを返します。成功の場合は0、エラーの場合は1以上です。の終了ステータスを確認してくださいcpcp通常、失敗した場合、エラーの内容を示すエラーメッセージを出力します。スクリプトでは、最後のコマンドの終了ステータスはマジック変数にあります$?

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/

コピーされたファイルが大きい理由については、それがスパースファイルであったためでなければなりません。スパースファイルは、nullバイトのみを含むブロックが保存されない粗い形式の圧縮です。ファイルをコピーすると、cpコマンドはヌルバイトを読み書きします。そのため、元のブロックに欠落ブロックがあった場合、コピーにはヌルバイトでいっぱいのブロックがあります。Linuxでは、cpコマンドはスパースファイルを検出しようとしますが、常に成功するとは限りません。cp --sparse=alwaysCPU時間のわずかな増加を犠牲にして、より困難になります。

より一般的には、du他の形式の圧縮により異なる結果を返す可能性があります。ただし、圧縮ファイルシステムはまれです。ファイルのサイズを、ファイルが使用するディスクブロックの数ではなく、ファイルのバイト数として知りたい場合は、のls -l代わりに使用しますdu


本当にありがとう!私のファイルがスパースかどうかを教えてくれる(別個の)ユーティリティがあるかどうか知っていますか?
アンドリュー

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.