Wann gibt "ls -s" "0" aus?


13

Die Standardmethode zum Testen, ob eine Datei leer ist test -s FILE, ist natürlich mit , aber einer unserer Kunden hat ein Skript erhalten, das Tests wie diese enthält:

RETVAL=`ls -s ./log/cr_trig.log | awk '{print $1}'`
if test $RETVAL -ne 0
then
    echo "Badness: Log not empty"
    exit 25
fi

Mit der Behauptung des Lieferanten, dass es in den beiden Umgebungen funktioniert, in denen es getestet wurde. Es erübrigt sich zu erwähnen, dass es an beiden Stellen, an denen ich es getestet habe, schwer fehlgeschlagen ist.

Also wurde ich neugierig. Wann wird für leere Dateien ls -sgedruckt 0?

Dies sind meine bisherigen Ergebnisse:

  • GFS unter Linux: 4
  • ext4 unter Linux: 0
  • ZFS unter Solaris: 1
  • UFS unter Solaris: 0
  • jfs unter AIX: 0
  • VxFS unter HP-UX: 0
  • HFS unter HP-UX: 0
  • HFS unter Mac OS X: 0

Ich habe vernetzte Dateisysteme noch nicht untersucht.

Frage: Wie kann ich den anderen elegant erklären, dass ihre Skripte falsch sind ?

Meiner Meinung nach wäre die "richtige" Version:

if test ! -s ./log/cr_trig.log
then
    echo "Badness: Log not empty"
    exit 25
fi

5
Zeigen Sie ihnen einfach Ihre Tests. Sie haben harte Daten, die beweisen, dass der Test nicht portabel ist. Was brauchen Sie noch?
Mat

Eine der interessantesten Fragen, die ich bisher auf diesem Server gesehen habe. Schade, dass man nur einen Punkt ausgeben kann.
ktf

@ktf Du kannst immer ein Kopfgeld gewähren.
Joe

Antworten:


6

Sehr interessante Entdeckung. Obwohl ich nie ls -süberprüft habe, ob eine Datei leer ist oder nicht, hätte ich angenommen, dass sie auch 0für leere Dateien meldet .

Zu Ihrer Frage: Wie Mat bereits kommentierte, zeigen Sie ihnen Ihre Testergebnisse. Um ihnen die Ergebnisse zu erläutern, geben Sie an, dass ls -sdie Anzahl der zugewiesenen Blöcke im Dateisystem und nicht die tatsächliche Größe in Bytes angegeben wird. Offensichtlich weisen einige Dateisystemimplementierungen Blöcke zu, auch wenn sie keine Daten speichern müssen, anstatt nur einen NULL-Zeiger im Inode zu speichern.

Die Erklärung hierfür kann leistungsbezogen sein. Das Erstellen leerer Dateien, die leer bleiben, ist eine Ausnahme für die normale Verarbeitung (die häufigste Verwendung, die ich gesehen habe, ist das Erstellen von Statusdateien, bei denen das Vorhandensein einer Datei einen bestimmten Status der Software darstellt).

Normalerweise erhält eine erstellte Datei jedoch bald einige Daten, sodass die Designer eines bestimmten FS möglicherweise davon ausgegangen sind, dass es sich auszahlt, einen Datenblock bei der Dateierstellung sofort zuzuweisen. Wenn also die ersten Daten eintreffen, ist diese Aufgabe bereits erledigt.

Der zweite Grund könnte sein, dass eine Datei in der Vergangenheit gelöschte Daten enthält. Anstatt den letzten Datenblock freizugeben, kann es sinnvoll sein, diesen Datenblock für die Wiederverwendung durch dieselbe Datei aufzubewahren.

BEARBEITEN:

Ein weiterer Grund kam mir in den Sinn: Die Dateisysteme, in denen Sie Werte> 0 gefunden haben, sind ZFS , die RAID + LVM + FS-Implementierung, und GFS , ein Cluster-Dateisystem. Beide müssen möglicherweise Metadaten speichern, um die Dateiintegrität aufrechtzuerhalten, die nicht in Inodes gespeichert ist. ls -sDies kann in Datenblöcken der Fall sein, die für diese Metadaten reserviert sind.


4

Im Gegensatz zu den meisten (wenn nicht allen) anderen Dateisystemen weist ZFS kein statisches Array von Inodes vorab zu. Beim Erstellen einer leeren Datei in ZFS wird dann ein neuer Datenblock verwendet, der von gemeldet wird ls -s.

Ich vermute, dass GFS Synchronisierungs- / Sperrdaten speichern muss, die zu dem anderen Ergebnis ungleich Null führen.


2

ls -s gibt die Anzahl der Blöcke an, die für die Datei reserviert sind, ohne die direkt im Verzeichniseintrag gespeicherten Blöcke.

In den meisten Fällen ist die Anzahl der Blöcke die Anzahl der Bytes geteilt durch die Blockgröße in Bytes, aufgerundet.

Die Anzahl der Blöcke kann geringer sein als bei einer Sparse-Datei . Beispielsweise wird auf den meisten Dateisystemen eine 8192-Byte-Datei erstellt, die sich über 0 Blöcke erstreckt:

$ perl -e 'truncate STDOUT, 8192' >a
$ ls -l a
-rw-r--r-- 1 gilles gilles 8192 Nov  1 21:32 a
$ ls -s a
0 a

Umgekehrt kann die Anzahl der Blöcke höher sein, wenn das Dateisystem Blöcke für Dateien vorbelegt oder Blöcke zum Speichern von Metadaten verwendet. Ich bin nicht überrascht, dass Zfs eine nicht offensichtliche Entsprechung zwischen Dateigröße und Anzahl der Blöcke aufweist, da es eine große Anzahl von Funktionen bietet und sich an großen Dateisystemen orientiert. Ich kenne die Details nicht, aber die Anzahl der Blöcke hängt nicht nur von der Größe der Dateien ab, sondern auch von deren Verlauf (Sie können mehr als einen Block in einer leeren Datei haben, wenn eine größere Datei abgeschnitten wurde).

Um zu erklären, warum ls -sdas falsch ist: Es zählt nicht die Größe der Datei, sondern eine vom Dateisystem abhängige Menge. Dies ist eine sehr indirekte Methode, um festzustellen, ob eine Datei überhaupt leer ist, und erfordert ein externes Tool ( ls) und eine Analyse. Stattdessen sollten sie verwenden test -s, was kein Parsing erfordert und genau das ausführt, was angefordert wird. Wenn sie der Meinung sind, dass dies ls -sein guter Weg ist, um zu testen, ob eine Datei leer ist, sollten sie die Verantwortung tragen, um zu rechtfertigen, dass sie funktioniert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.