page header

juni 2009 Archieven

Vol filesysteem en output redirection


Geplaatst door miekg op wo jun 24 10:39:42 CEST 2009 | Permanente link | Categorie: Systeembeheer | Reacties: 0

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.