Tijdens het geven van een cursus maakte een cursist mij attent op
het volgende:
$ ps -ef > /tmp/file
op een vol filesystem (/tmp is 100% gevuld) geeft dit geen foutmelding!
Dit artikel beschrijft de achter liggende oorzaken en geeft een
verklaring voor dit gedrag.
Eerst is het zaak om een filesystem (partitie) 100% gevuld te krijgen.
Het filesystem dat we gebruiken is gemount onder /media/disk.
$ cp /dev/zero /media/disk/GROTEFILE
cp: writing `/media/disk/GROTEFILE': No space left on device
Om te testen maken we een klein test programmaatje in C:
int
main(void)
{
write(1, "hallo\n", 6);
}
Dit schrijft 6 bytes hallo\n naar standard output. Let op: we
vergeten hier opzettelijk om te controleren of het schrijven goed
is gegaan. De write() system call geeft namelijk terug hoeveel
karakters er daadwerkelijk zijn geschreven. Zie ook man 2 write.
Na een compilatie hebben we ons programmaatje schrijf:
$ gcc schrijf.c -o schrijf
Nu kunnen we de normale input/output redirection toepassen en die
doet wat je verwacht:
$ ./schrijf > tijdelijke_file
$ cat tijdelijke_file
hallo
Laten we dit nu eens uit proberen op het filesysteem dat 100% vol is.
$ ./schrijf > /media/disk/tijdelijke_file
Geen foutmeldingen – dus blijkbaar is het goed gegaan.
$ ls -l /media/disk/tijdelijke_file
-rw-rw-r-- 1 miekg miekg 0 Jun 10 12:47 /media/disk/tijdelijke_file
De file is blijkbaar wel aangemaakt, maar heeft als grootte 0 bytes. We
kunnen ons nu 2 vragen stellen. Waarom is de file eigenlijk aangemaakt,
het filesystem zat toch vol? En ten tweede, waarom zit er geen data in
de file aangezien er geen enkele foutmelding is?
Directories
Als je onder Linux (en ook Unix) een directory aanmaakt dan geeft ls
-ldh weer dat deze (lege) directory 4.0K groot is:
$ mkdir /tmp/test
$ ls -ldh /tmp/test
drwxrwxr-x 2 miekg miekg 4.0K Jun 10 12:52 /tmp/test
De 4.0K wordt alvast gereserveerd, als ik nu files (en/of
subdirectories) aanmaak onder /tmp/test zal de grootte van
de directory /tmp/test pas vergroot worden als we over
de 4.0K heen gaan. Typisch wordt de grootte dan 12.0K (op Linux)
$ cd /tmp/test
$ for i in $(seq 0 260); do echo $i; touch file.$i; done
$ ls -ldh /tmp/test
drwxrwxr-x 2 miekg miekg 12K Jun 10 12:59 /tmp/test
Dus zolang je de reservering niet overschrijdt kun je (lege) files
blijven aanmaken.
Op een vol filesysteem is het meestal nog mogelijk om een file
aan te maken als je daarmee maar niet de reservering overschrijdt.
Schrijven van de data
Als we ./schrijf > media/disk/tijdelijke_file opschrijven, dan
weet schrijf niet dat hij naar disk schrijft. schrijf schrijft
naar zijn stdout. En in dit geval controleert schrijf ook niet of het
schrijven gelukt is. Als we deze controle wel inbouwen, dan is de
situatie geheel anders.
Eerst passen we de source aan:
int
main(void)
{
if (write(1, "hallo\n", 6) != 6) {
write(2, "schrijf: schrijf fout\n", 20);
return 1;
}
return 0;
}
Opnieuw compileren
$ gcc schrijf.c -o schrijf
Opnieuw testen met:
$ ./schrijf > /media/disk/tijdelijke_file
schrijf: schrijf fout
Nu is in schrijf dit euvel verholpen, maar het zal je misschien
verbazen dat het ook in andere programma’s mis gaat.
De volgende commando’s gaan allemaal de mist in zonder een foutmelding
te geven:
$ ps -ef > /media/disk/tijdelijke_file
$ free > /media/disk/tijdelijke_file
$ grep 'as' testfile > /media/disk/tijdelijke_file
$ perl -e 'print "hallo";' > /media/disk/tijdelijke_file
Gelukkig zijn er ook nog programma’s die het wel goed doen:
$ who > /media/disk/tijdelijke_file
who: write error: No space left on device
Ook veel (zo niet alle) programma’s gemaakt door
GNU vertonen het juiste gedrag.