Hoofdstuk 6. Input en output

Inhoudsopgave

Eenvoudige redirections
Wat zijn standaard input, output en error?
De output redirection operatoren
Pipes en output redirection combineren
Geavanceerd gebruik van redirection
Het gebruik van descriptoren
Het tee commando
Filters
Output herstructureren
Meer grep toepassingen
Het sort commando
Samenvatting

Samenvatting

Dit hoofdstuk is cruciaal in het leerprocess van elke UNIX- of Linuxstudent. We zullen dieper ingaan op de funktionaliteiten van de shell om ons systeem optimaal te kunnen gebruiken. Volgende onderwerpen komen ter sprake:

  • Wat zijn standaard output, input en error?

  • Output wordt input.

  • Hoe stuur ik output naar een bestand?

  • Hoe voorkom ik het overschrijven van bestanden?

  • Verschillende commando's combineren.

  • Hoe kan ik output filteren?

  • Wat kan ik doen met foutboodschappen?

Eenvoudige redirections

Wat zijn standaard input, output en error?

De meeste Linux commando's lezen input, zoals de inhoud van een bestand, argumenten en opties. Ze schrijven output. Standaard komt de input van het toetsenbord, output komt op het scherm in een terminal venster.

Je toetsenbord wordt het standaard input apparaat genoemd. Men kort dit af als stdin.

Je scherm noemt men het standaard output apparaat, afgekort als stdout.

Foutmeldingen van commando's worden als een appart type output behandeld, hoewel ze standaard naar hetzelfde apparaat als de standaard output gestuurd worden. Die foutmeldingen noemt men standaard error, afgekort stderr.

[Opmerking]Moet dat allemaal in het Engels?

In dit hoofdstuk worden tamelijk veel Engelse termen gebruikt. Enerzijds is dit om je gewend te maken aan de vakliteratuur, anderzijds zijn er in veel gevallen geen Nederlandse namen voorhanden. Zelf namen verzinnen leek ons niet erg nuttig, gezien zo'n zelfverzonnen termen nergens anders voorkomen; mocht je ze gebruiken in een zoekmachine zoals Google, zou je geen resultaten terugkrijgen. Dus houden we ons grotendeels aan de Engelse termen.

Linux is een zeer flexibel systeem. De standaard instellingen hoeven niet noodzakelijk. Zo zou standaard input een bestand kunnen zijn in plaats van een toetsenbord, en standaard output zou een printer kunnen zijn in plaats van je scherm. In de volgende sekties bespreken we de vele mogelijkheden van deze zogenaamde redirection: een ander apparaat dan het standaard apparaat gebruiken als input, output en/of error.

De output redirection operatoren

De > operator

Gebruik

Als je de output van een commando wilt opslaan in een bestand, gebruik je de “>” operator na het commando, gevolgd door de naam van het bestand waarin je de output kwijt wilt:

commando [opties} [argumenten] > bestandsnaam

Een voorbeeld:

[Belangrijk]Output naar een bestand sturen
willy@ubuntu:~$ date
za jun 29 08:49:41 CEST 2006
willy@ubuntu:~$ date > datum
willy@ubuntu:~$ cat datum
za jun 29 08:49:41 CEST 2006
willy@ubuntu:~$ ls -l > mijn_home_vandaag
willy@ubuntu:~$ cat datum mijn_home_vandaag > mijn_home_20060629

Wat zit er in het bestand mijn_home_20060629?

[Tip]De datum in bestandsnamen

We zagen reeds eerder het gebruik van de zogenaamde backticks. Probeer in plaats van zelf de datum op te geven eens het volgende:

willy@ubuntu:~$ cat datum mijn_home_vandaag > mijn_home_`date +%y%m%d`

Meer in de man pagina's van date.

Overschrijven voorkomen

Wees voorzichtig als je op deze manier de output van een commando in een bestand steekt. Als de opgegeven bestandsnaam reeds bestaat, zal de inhoud zonder waarschuwing overschreven worden.

Wil je niet het risico lopen om bestanden te overschrijven, geef dan eerst het volgende commando in:

set -o noclobber

Dit instrueert je shell om een melding te geven wanneer je dreigt een bestaand bestand te overschrijven.

[Belangrijk]Een test

Probeer:

  • Maak een testbestand aan met touch.

  • Geef de shell de noclobber optie mee.

  • Probeer de output van het date commando in het testbestand te steken.

Wat bemerk je?

Open een nieuw terminal venster en probeer daarin het testbestand te overschrijven met de output van het date commando. Wat gebeurt er?

We zullen in het derde lespakket zien hoe we deze optie permanent kunnen maken.

Beknotten van bestanden

Als we “niets” naar een bestaand bestand sturen, is dat hetzelfde als het bestand leegmaken. Let in het volgende voorbeeld op de grootte van het bestand:

[Belangrijk]Bestanden leegmaken
willy@ubuntu:~$ ls -l mijn_home_060626
-rw-r--r-- 1 willy willy 877 2006-06-29 08:54 mijn_home_060626
willy@ubuntu:~$ > mijn_home_060626
willy@ubuntu:~$ ls -l mijn_home_060626
-rw-r--r-- 1 willy willy   0 2006-06-29 08:54 mijn_home_060626

Dit beknotten of leegmaken van bestanden noemt men truncating.

De | operator

Gebruik

De “|” operator wordt gebruikt om de output van een commando te gebruiken als input voor een tweede commando.

Het vertikale streepje noemt men in het Engels een pipe. Vandaar dat dit proces ook wel eens pipen genoemt wordt. De Nederlandse term is pijplijn.

Voorbeeld van een pipe met ps en grep

In het vorige hoofdstuk zagen we dat proceslijsten vaak heel lang kunnen zijn. Soms zijn ze zo lang, dat je terminalbuffer overstroomt. In dat geval kan je het schuivertje rechts van het venster niet gebruiken om helemaal naar het begin van de output terug te rollen. Bovendien is het sowieso niet handig om telkens te moeten gaan zoeken in zoveel output. Met een pipe en het grep commando kunnen we veel handiger en sneller werken. Bijvoorbeeld om enkel het browserproces te tonen:

[Belangrijk]Combineer ps en grep

Zorg ervoor dat je eerst de browser gestart hebt, via het ikoon in de bovenste taakbalk of via de commandoregel.

willy@ubuntu:~$ ps -ef | grep fire
willy	7871	1 15 09:06 ? 	    00:00:04 /usr/lib/mozilla-firefox/firefox
-bin -a firefox
willy 	7902 7296  0 09:07 pts/0    00:00:00 grep fire

Op systemen die weinig belast zijn, krijg je wel eens het grep commando zelf te zien, naast de lijnen die je eigenlijk gevraagd had.

Voorbeeld van een pipe met ls en grep

Een lange lijst van alle bestanden in de /etc map werkt niet handig. Stel dat we alle bestanden willen zien die met cron te maken hebben:

[Belangrijk]Lange lijsten voorkomen
willy@ubuntu:~$ ls -l /etc | grep cron
-rw-r--r--  1 root  root    364 2005-05-03 04:10 anacrontab
drwxr-xr-x  2 root  root   4096 2006-06-06 14:20 cron.d
drwxr-xr-x  2 root  root   4096 2006-06-06 14:23 cron.daily
drwxr-xr-x  2 root  root   4096 2006-06-06 14:20 cron.hourly
drwxr-xr-x  2 root  root   4096 2006-06-06 14:26 cron.monthly
-rw-r--r--  1 root  root    651 2005-05-03 01:09 crontab
drwxr-xr-x  2 root  root   4096 2006-06-06 14:20 cron.weekly

Noteer dat ls de lijnen alfabetisch sorteert. Het enige dat grep doet, is de lijnen met de gevraagde string eruithalen en op het scherm zetten. Bijgevolg is ook deze output alfabetisch gesorteerd.

Voorbeeld van een pipe met ls en less

Wil je toch alles zien in een lange lijst die niet op het scherm kan, gebruik dan het volgende commando:

ls -l map | less

Gebruik de normale toetsen om binnen het less commando te navigeren.

Voorbeeld met twee pipes

Nemen we weer het voorbeeld van de paragraaf “Voorbeeld van een pipe met ls en grep”. Als we nu uit deze output enkel de lijnen willen die de string “crontabniet bevatten, dan maken we de pijplijn wat langer, door de output van het grep commando te gebruiken voor een tweede grep:

[Belangrijk]Twee pipes
willy@ubuntu:~$ ls -l /etc | grep cron | grep -v crontab
drwxr-xr-x  2 root  root   4096 2006-06-06 14:20 cron.d
drwxr-xr-x  2 root  root   4096 2006-06-06 14:23 cron.daily
drwxr-xr-x  2 root  root   4096 2006-06-06 14:20 cron.hourly
drwxr-xr-x  2 root  root   4096 2006-06-06 14:26 cron.monthly
drwxr-xr-x  2 root  root   4096 2006-06-06 14:20 cron.weekly

De >> operator

De >> operator wordt gebruikt om output van een commando aan een bestaand bestand te hangen, zonder de inhoud te overschrijven. Neem er nog even de oefening van de paragraaf “Gebruik” bij. Daarin maakten we twee bestanden aan, datum en mijn_home_vandaag, die we later samenvoegden tot één enkel bestand. Dit kan ook in één stap:

[Belangrijk]Doe mee

Dit is een goede oefening om het gebruik van de shell in de vingers te krijgen.

willy@ubuntu:~$ date > mijn_home_`date+%y%m%d` ; ls -l >> mijn_home_`date+%y%m%d`

Met echo zijn er ook vele mogelijkheden:

willy@ubuntu:~$ echo "meer geld" > verlanglijstje
willy@ubuntu:~$ echo "minder werk" >> verlanglijstje
willy@ubuntu:~$ date >> verlanglijstje
willy@ubuntu:~$ cat verlanglijstje
meer geld
minder werk
za jun 29 09:36:12 CEST 2006

De < operator

Iets moeilijker om te begrijpen is de input redirection. De operator is “<” en wordt gebruikt om bijvoorbeeld een bestand als input te gebruiken voor een commando dat in normale omstandigheden geen bestanden als input zou aanvaarden. Input redirection leest moeilijker dan output redirection, het komt doorgaans niet natuurlijk over en wordt daarom enkel gebruikt door gevorderden.

Pipes en output redirection combineren

Het gebeurt zeer vaak dat verschillende operatoren gecombineerd worden in een commando. De output van een pijplijn, die kan bestaan uit één of meerdere pipes, wordt dikwijls opgeslagen in een bestand.

Een voorbeeld: al je eigen processen in een bestand steken:

[Belangrijk]Jouw processen
willy@ubuntu:~$ ps -ef | grep willy > mijn_processen

Nu kan je rustig met less het bestand mijn_processen bestuderen. Of je had natuurlijk ook een pipe met daarachter less kunnen gebruiken.

[Belangrijk]Hoofding

Als je bovenstaand commando gebruikt, hebben de kolommen in de output geen hoofdingen. Hoe krijg je de titels van de kolommen ook in het bestand mijn_processen?