Geavanceerd gebruik van redirection

Het gebruik van descriptoren

De drie I/O types

We zagen reeds dat er drie types I/O zijn. Elk krijgt een nummer toegewezen:

  • Standaard input: 0

  • Standaard output: 1

  • Standaard error: 2

Deze nummers noemt men de file descriptors. Er zijn nog andere file desriptoren, maar die zijn bedoeld voor gevorderde gebruikers.

De file descriptoren per proces worden bijgehouden in /proc. Daar heb je per PID een map, met daarin een submap fd, met daarin alle filedescriptoren die aan een proces verbonden zijn. Aan een shell proces zijn altijd de descriptoren voor standaard input, output en error verbonden. Het gebruik van nummers en links in plaats van lange namen bespaart geheugenruimte.

Voorbeelden

Standaard output en standaard error naar hetzelfde bestand sturen

In het volgende voorbeeld gaan we na in welke configuratiebestanden onze gebruikersnaam voorkomt:

Handeling met de muis.

willy@ubuntu:~$ grep willy /etc/*
grep: /etc/at.deny: Toegang geweigerd
grep: /etc/group-: Toegang geweigerd
grep: /etc/gshadow: Toegang geweigerd
grep: /etc/gshadow-: Toegang geweigerd
grep: /etc/passwd-: Toegang geweigerd
grep: /etc/shadow: Toegang geweigerd
grep: /etc/shadow-: Toegang geweigerd
grep: /etc/sudoers: Toegang geweigerd

Al de lijnen met de string “Toegang geweigerd” zijn standaard error. Als we de output van een commando naar een bestand sturen, is standaard error daar normaalgezien niet bij. Wil je toch ook deze lijnen opslaan, gebruik dan de volgende constructie:

Handeling met de muis.

willy@ubuntu:~$ grep willy /etc/* > willy_in_etc 2>&1

Dit instrueert de shell om de standaard errorboodschappen naar dezelfde plaats te sturen als de standaard output.

[Waarschuwing]& en >

Verwar de opdracht “>&” niet met het gebruik van de ampersant om een commando in de achtergrond te plaatsen, noch met het gebruik van het groter dan teken om output naar een bestand te sturen. De uitdrukking “>&” vormt één geheel voor de shell die het commando inleest.

[Opmerking]Output redirection en cron

Taken uitgevoerd door cron zijn niet verbonden aan een terminal. Denk maar aan het tijdstip wanneer ze uitgevoerd worden: bijvoorbeeld midden in de nacht, als er niemand op het systeem aangemeld is. Er is dus geen manier voor cron om de standaard output en standaard error ergens kwijt te geraken. Als een commando output of errors genereert, zal de taak mislukken wanneer je er niet aan gedacht hebt om de output ergens op te slaan. Laat lijnen in de crontab daarom voor de zekerheid altijd eindigen op “> logbestand 2>&1”. Bijvoorbeeld in de crontab lijn van de paragraaf “De crontab editeren” (ingekort zodat de opdracht elk half uur uitgevoerd wordt):

0,30 * * * * touch /var/tmp/`date` > /var/tmp/cron.out 2>&1
[Tip]Ouput weggooien

Als je echt absoluut zeker bent dat de output en de errors van een lijn in de crontab niet belangrijk zijn, of onbestaande, gebruik dan het bestand /dev/null om de output en de errors naartoe te sturen. Dit bestand is een bodemloze put. Je kan er alles naartoe sturen en het komt er nooit meer uit. Het is een eenvoudige manier om bestanden te verwijderen door redirection, zo moet je niet telkens het rm commando oproepen.

Enkel standaard error naar een bestand sturen

Nemen we weer het voorbeeld van de paragraaf “Standaard output en standaard error naar hetzelfde bestand sturen”. Ditmaal willen we enkel de standaard error in een bestand zien, de output gaat gewoon naar het scherm. Dat doe je als volgt:

[Belangrijk]Standaard error scheiden van standaard output

Uiteraard voer je je eigen gebruikersnaam in in plaats van de naam “willy” in ons voorbeeld.

willy@ubuntu:~$ grep willy /etc* 2> fouten

Zoals je zal zien, komt de standaard output in je scherm. Kijk met cat na wat de inhoud van het bestand fouten is.

Standaard output en standaard error naar verschillende bestanden sturen

Uiteraard is het ook mogelijk om zowel standaard output als standaard error naar een verschillend bestand te sturen. Vergeet niet dat je nog steeds moet uitkijken dat je niet per ongelijk bestaande bestanden overschrijft.

We werken nog steeds met hetzelfde voorbeeld:

[Belangrijk]Output en error naar verschillende bestanden
willy@ubuntu:~$ grep willy /etc* > willy_in_etc 2> fouten

Kijk weer na met cat of less of het commando wel degelijk volgens de verwachtingen gewerkt heeft.

Het tee commando

Doel

Soms wil je de output van een commando naar meerdere bestanden sturen. Het tee maakt zo'n opsplitsing. Bovendien kan je met de -a optie output aan bestaande bestanden hangen zonder te overschrijven, zoals we al deden met de >> operator. Het tee commando gebruik je ook als je tegelijk de output wilt zien en hem additioneel ook wilt opslaan. De > en >> operatoren laten niet toe om deze twee akties simultaan uit te voeren.

Het tee commando wordt vaak gebruikt na een pipe.

Voorbeeld

In onderstaand voorbeeld wordt de output van het date commando opgeslagen in twee bestanden. Daarna wordt de output van het uptime commando aan het tweede bestand gehangen.

[Belangrijk]Werken met tee
willy@ubuntu:~$ date | tee bestand1 bestand2
do jun 29 05:28:02 CEST 2006
willy@ubuntu:~$ cat bestand1
do jun 29 05:28:02 CEST 2006
willy@ubuntu:~$ cat bestand2
do jun 29 05:28:02 CEST 2006
willy@ubuntu:~$ uptime | tee -a bestand2
05:29:55 up 16 min, 2 users, load average: 0.00, 0.14, 0.23
willy@ubuntu:~$ cat bestand2
do jun 29 05:28:02 CEST 2006
05:29:55 up 16 min, 2 users, load average: 0.00, 0.14, 0.23

Merk op dat de output steeds zowel op het scherm als in de opgegeven bestanden komt.