du vs. ls vs. df

Wer die Unix-Befehle du, ls und df gerade zum ersten mal hört, kann hier aufhören zu lesen. Alle anderen: Willkommen zu unseren heutigen Diskussionsrunde. Ich möchte heute ein in meinen Augen sehr interessantes Thema ansprechen. Dazu haben wir folgende Testumgebung. Zum selber machen:

dd if=/dev/zero of=mountme.img bs=1024 count=0 seek=$[1024*1024] mkfs.ext3 mountme.img mkdir mount && sudo mount mountme.img mount/ dd if=/dev/zero of=mount/image.img bs=1024 count=0 seek=$[1024*100]
Was passiert in den vier Zeilen? Erst erstellen wir ein Image von einem Gigabyte Namens mountme.img und formatieren es mit ext3. Danach erstellen wir den Ordner "mount" und binden es dort ein. Wir haben nun eine zweite Partition, auf die wir zugreifen können (mehr dazu später). Dort wird mit der letzten Zeile ein weiteres Image Namens image.img mit einer Größe von 100MB erstellt.

Das interessante daran ist nun der seek-Teil im dd-Befehl. Er sorgt dafür, dass die 10MB nicht mit Nullen vollgeschrieben werden, sondern dass der Platz nur allokiert wird. Das bedeutet, dass das Dateisystem einen Start- und einen Endpunkt angibt und sagt: “So, und der Teil zwischen Start und Ende ist für das Image reserviert, aber noch nicht beschrieben.” Das Image hat auf der Platte somit keine 100MB belegt, sondern nur reserviert.

Untersuchen wir das Phänomen doch einmal. Wie wärs mit einem ls?

$ ls -lh mount total 0 -rw-rw-r-- 1 geiger geiger 100M Okt 18 15:31 image.img
Interessant. Neben der Datei wird wie erwartet 100M ausgegeben, da das Image ja 100M reserviert hat, die nun für nichts anderes mehr benutzt werden können. Guckt man sich aber den total-Count an, der in der ersten Zeile der Ausgabe steht, sieht man die tatsächliche Bytegröße: 0. Etwas verwirrend, oder? Sollte da nicht 100M stehen?

Warum dem nicht so ist, wird deutlich, wenn wir mal den Befehl du (disk usage) auf den Ordner mount abfeuern. Wir sehen:

$ du -ah mount 0 mount/image.img 4,0K mount
Die Image-Datei hat also tatsächlich nicht einen Byte auf der Platte beschrieben. Diese Ausgabe ist auf den ersten Blick auch wieder etwas seltsam, jedoch nachvollziehbar, da das Programm ja disk usage heißt. Wenn es also nur den tatsächlichen Verbrauch ausgibt, sei ihm verziehen. Hängen wir ein --apparent-size an, wird die reservierte Größe wie erwartet angezeigt:
$ du -ah --apparent-size mount 100M mount/image.img 101M mount
Und jetzt kommts: df, was für "disk free" steht und den freien bzw. belegten Speicherplatz eines Dateisystems ausgibt, wirft folgende Ausgabe:
$ df -h mount Filesystem Size Used Avail Use% Mounted on /dev/loop0 1008M 34M 924M 4% /home/geiger/foo/mount
Wir sehen 34M, die belegt sind. Diese kommen durch die Dateisysteminformationen von ext3. Warum werden aber die 100M nicht mitberechnet? In meinen Augen ist das ein Fehlverhalten von df, da damit ja der tatsächlich freie Speicherplatz angezeigt werden soll und nicht der Platz, der auf dem Datenträger wirklich belegt ist. So läuft man relativ schnell ins Messer, wenn man viele Images auf der Platte hat und diese allmählich vollläuft. Update: Die 100M werden nicht angezeigt, weil sie noch zur Verfügung stehen. Mein Problem ist somit also geklärt. Es ist auf den ersten Blick etwas verwirrend, aber doch korrekt. Die einzige Sache, die meiner Meinung nach nicht ganz optimal gelöst ist, ist die total-Anzeige bei ls. Aber auch diese hat ihre Daseinsberechtigung, allein schon aus performancetechnischer Sicht.