du gibt zwei verschiedene Ergebnisse für dieselbe Datei an

23

Ich bin ein Doktorand der Computerchemie mit Zugang zu einem Linux-Cluster. Der Cluster besteht aus einem sehr großen (25 TB) Dateiserver, an den mehrere Dutzend Rechenknoten angeschlossen sind. Jeder Rechenknoten besteht aus 8 bis 24 Intel Xeon-Kernen. Jeder Rechenknoten enthält außerdem eine lokale Festplatte mit etwa 365 TB.

Da etwa ein Dutzend Benutzer in der Forschungsgruppe routinemäßig auf den Dateiserver zugreifen, wird der Dateiserver hauptsächlich für die Langzeitspeicherung von Dateien verwendet (er wird jede Nacht gesichert, während die lokalen Datenträger der Rechenknoten nie gesichert werden). Aus diesem Grund hat der Systemadministrator uns angewiesen, Simulationen auf den lokalen Datenträgern durchzuführen, die schneller als der Dateiserver sind, um den Dateiserver für die anderen Benutzer nicht zu verlangsamen.

Also führe ich Simulationen auf den lokalen Festplatten aus und kopiere dann, nachdem sie fertig sind, die Trajektoriendateien - ich führe Molekulardynamik-Simulationen (MD-Simulationen) - zum Speichern auf den Dateiserver. Angenommen, ich habe eine Trajektoriedatei, die traj.trrin einem Verzeichnis auf der lokalen Festplatte eines Knotens aufgerufen wird /home/myusername/mysimulation1/traj.trr. Für die Langzeitspeicherung kopiere ich immer traj.trrin ein Verzeichnis auf dem Dateiserver, ~/mysimulation1/traj.trrin dem ~mein Verzeichnis auf dem Dateiserver steht /export/home/myusername. Nachdem ich es kopiert habe, du -hüberprüfe ich gewöhnlich , ob /home/myusername/mysimulation1/traj.trres dieselbe Dateigröße hat wie ~/mysimulation1/traj.trr. Auf diese Weise kann ich zumindest einigermaßen sicher sein, dass die Übertragung auf den Dateiserver erfolgreich war. Beispielsweise:

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

Wenn die beiden Aufrufe du -hdieselbe für Menschen lesbare Dateigröße ergeben, kann ich mit ziemlicher Sicherheit davon ausgehen, dass die Übertragung / Kopie erfolgreich war. (Meine typischen traj.trrDateien haben eine Größe von 15 bis 20 GB, abhängig von der genauen Simulation, die ich ausgeführt habe.) Wenn ich die beiden Dateien du(dh ohne den -hSchalter) ausführe traj.trr, sind ihre Größen in Bytes normalerweise sehr, sehr ähnlich. - In der Regel innerhalb weniger Bytes. Ich verwende diese Gesamtmethode seit anderthalb Jahren ohne Probleme.

In letzter Zeit bin ich jedoch auf folgendes Problem gestoßen: Manchmal wirddu -hberichtet, dass sich die beidentraj.trrDateien in der Größe um mehrere GB unterscheiden. Hier ist ein Beispiel:

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

Die Ausgabe der beiden Aufrufe an du -hlautet wie folgt:

20G     traj.trr
28G     traj.trr

Ich glaube, dass die erstere (dh die traj.trrauf der lokalen Festplatte /home/myusername/mysimulation1/) die richtige Dateigröße hat, da meine Simulationsverläufe voraussichtlich jeweils etwa 15 bis 20 GB betragen. Aber wie könnte die Datei auf dem Dateiserver tatsächlich größer sein ? Ich konnte sehen, wie es kleiner sein könnte, wenn die cpÜbertragung irgendwie fehlschlug. Aber ich sehe nicht ein, wie es tatsächlich größer sein könnte .

Ich erhalte eine ähnliche Ausgabe, wenn ich die gleichen Befehle wie oben ausführe, aber ohne den -hSchalter für du:

20717480        traj.trr
28666688        traj.trr

Können Sie sich einen Grund für den Unterschied vorstellen?

Wenn es durch einen unwahrscheinlichen Zufall zu einer duFehlfunktion kommt, kann ich damit einverstanden sein. Aber ich muss wirklich nur sicherstellen, dass die Kopie von traj.trrauf dem Dateiserver vollständig und mit der Quellversion auf der lokalen Festplatte identisch ist. Ich muss die lokale Datei löschen, damit ich genug lokalen Speicherplatz habe, um neue Simulationen auszuführen, aber ich kann es mir nicht leisten, die Version von traj.trrauf dem Dateiserver zu beschädigen.

Das .trr-Dateiformat (aus dem Gromacs Molecular Dynamics-Paket) ist ein Binärformat, kein Text. Daher bin ich mir nicht sicher, ob die Dateien von einem Programm wie z. B. zuverlässig verglichen werden können diff.

Andrew
quelle
5
Versuchen Sie, md5sumoder sha1sumauf den Dateien auszuführen. Passen sie zusammen?
cjm
2
@cjm Ich habe gerade md5sumdie beiden Dateien bearbeitet . Die beiden Prüfsummen stimmen überein. Das heißt also, dass die beiden Dateien identisch sind?
Andrew
3
Welche Größen werden von gemeldet ls -l? Der Befehl gibt an du, wie viel Speicherplatz auf der Festplatte für Ihre Datei verwendet wird, nicht wie groß Ihre Datei ist. Die Größe der Festplatte kann durch Ihr Dateisystem und dessen Zuordnungsstrategien beeinflusst werden.
Casey
2
@casey ls -l -hsagt, dass beide Dateien 20 GB groß sind. Ebenso ls -lheißt es, dass beide Dateien 21214683940 Bytes sind. Ich schätze, die Dateien haben die gleiche Größe, belegen aber nicht den gleichen Speicherplatz (laut du).
Andrew
2
@ Andrew Da die von ls angegebenen Größen gleich sind und die Hashes gleich sind, können Sie daraus schließen, dass die Dateien gleich sind. Diese Tools geben Ihnen das nötige Vertrauen und zeigen Ihnen, dass du nicht das Tool ist, das Ihre Anforderungen erfüllt.
Casey

Antworten:

32

Sie sollten wirklich etwas wie md5sumoder verwenden sha1sum, um die Integrität zu überprüfen.

Wenn Sie die Größe wirklich verwenden möchten, verwenden Sie ls -loder du -b.

Das duDienstprogramm zeigt normalerweise nur die Plattenbelegung der Datei an, dh wie viel des Dateisystems von ihr verwendet wird. Dieser Wert hängt vollständig vom Backup-Dateisystem und anderen Faktoren ab, wie z. B. Dateien mit geringer Dichte.

Beispiel:

$ 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

Wir haben zwei Dateien mit jeweils 512 MB Nullen. Der erste ist sparsam gespeichert und belegt keinen Speicherplatz, während der zweite jedes Byte explizit auf der Festplatte speichert. - Gleiche Datei, aber völlig andere Datenträgerverwendung.

Die -bOption könnte gut für Sie sein:

   -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
michas
quelle
8

Dies ist ein häufiges Problem, wenn Sie dieselben Daten auf zwei verschiedenen Festplatten speichern. Sie möchten den duBefehl mit und einem zusätzlichen Schalter ausführen , vorausgesetzt, er verfügt über einen solchen - vorausgesetzt, es handelt sich um Linux-Knoten.

Der Schalter?

   --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

Beispiel

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

Die oben genannten Dateisysteme sind eine lokale Festplatte ( /root), während die andere /home/sameine NFS-Freigabe von meinem NAS ist.

$ 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

Na, was is los?

Dies verwirrt viele Menschen, aber denken Sie daran, dass Dateien, die auf einer Festplatte gespeichert werden, Speicherplatz belegen, auch wenn sie nur einen Teil dieser Blöcke verwenden. Wenn Sie duohne ausgeführt werden, erhalten --apparent-sizeSie die Größe basierend auf dem verwendeten Speicherplatz der Festplatte und nicht auf dem tatsächlich von den Dateien belegten Speicherplatz.

Verwenden Sie stattdessen eine Prüfsumme?

Dies ist wahrscheinlich die bessere Option, wenn Sie zwei Dateibäume vergleichen möchten. Mit diesem Befehl können Sie eine Prüfsumme für alle Dateien und anschließend eine endgültige Prüfsumme für die Prüfsummen berechnen. In diesem Beispiel wird verwendet, sha1sumaber Sie können es genauso einfach verwenden md5sum.

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

Beispiel

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

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

So können wir sehen, dass die 2 Bäume identisch sind.

(Hinweis: Mit dem Befehl find werden die Dateien so aufgelistet, wie sie im Dateisystem angezeigt werden. Wenn Sie also zwei Verzeichnisse aus einem anderen Dateisystem (z. B. Ext3 oder APFS) vergleichen, müssen Sie zuerst sortieren, bevor die endgültige Summe (hinzugefügt von) angezeigt wird Xianjun Dong)

slm
quelle
5

Die kurze Antwort: Testen Sie nicht die Dateigröße, sondern den Rückgabestatus des Befehls. Der Rückgabestatus ist der einzige verlässliche Hinweis darauf, ob der Kopiervorgang erfolgreich war (kurz, wenn die beiden Dateien byteweise direkt oder indirekt verglichen wurden - was redundant ist, wenn der Kopiervorgang erfolgreich war).

Das Überprüfen der Dateigröße ist keine sehr nützliche Methode, um zu überprüfen, ob eine Kopie erfolgreich war. In einigen Fällen kann dies eine nützliche Überprüfung der Datenintegrität sein, z. B. wenn Sie eine Datei aus dem Internet herunterladen. Aber hier gibt es einen besseren Weg.

Alle Unix-Befehle geben einen Status zurück, der angibt, ob sie erfolgreich waren: 0 für Erfolg, 1 oder mehr für Fehler. Überprüfen Sie daher den Ausgangsstatus von cp. cpNormalerweise wird eine Fehlermeldung ausgegeben, die angibt, um welchen Fehler es sich handelt. In einem Skript befindet sich der Beendigungsstatus des letzten Befehls in der magischen Variablen $?.

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

Anstatt zu prüfen, ob $?Null ist, können Sie Boolesche Operatoren verwenden.

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

Wenn Sie ein Skript ausführen und möchten, dass das Skript beendet wird, wenn ein Befehl fehlschlägt, führen Sie es aus set -e. Wenn ein Befehl fehlschlägt (dh einen Nicht-Null-Status zurückgibt), wird das Skript sofort mit demselben Status wie der Befehl beendet.

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

Der Grund dafür, dass Ihre kopierte Datei größer war, muss sein, dass es sich um eine spärliche Datei handelte . Sparse-Dateien sind eine grobe Form der Komprimierung, bei der Blöcke, die nur Null-Bytes enthalten, nicht gespeichert werden. Wenn Sie eine Datei kopieren, cpliest und schreibt der Befehl Null-Bytes. Wenn also im Original Blöcke fehlen, enthält die Kopie Blöcke mit Null-Bytes. Unter Linux versucht der cpBefehl, Dateien mit geringer Dichte zu erkennen, dies gelingt jedoch nicht immer. cp --sparse=alwaysmacht es schwieriger auf Kosten einer sehr geringfügigen Erhöhung der CPU-Zeit.

Im Allgemeinen können duandere Ergebnisse aufgrund anderer Komprimierungsformen zurückgegeben werden. Komprimierte Dateisysteme sind jedoch selten. Wenn Sie die Größe einer Datei anhand der Anzahl der Bytes in der Datei im Gegensatz zur Anzahl der verwendeten Plattenblöcke ermitteln möchten, verwenden Sie ls -lanstelle von du.

Gilles 'SO - hör auf böse zu sein'
quelle
Vielen Dank! Wissen Sie, ob es ein (separates) Dienstprogramm gibt, mit dem ich feststellen kann, ob meine Datei dünn ist oder nicht?
Andrew
@ Andrew Siehe Suchen von Dateien mit geringer Dichte ? und Detaillierte Informationen zu spärlichen Dateien unter Linux
Gilles 'SO - hör auf, böse zu sein'