College diktaat UNIX

Een introduktie voor beginnende UNIX gebruikers

Arjen Baart <arjen@andromeda.nl>

Feb 04, 1994

Document Information
Version 1.1
Organization Andromeda Technology & Automation

Table Of Contents

1 In- en uitloggen

2 Commandos

3 Files

4 Directories

5 vi

6 Netwerken

7 Communicatie met gebruikers

8 De Shells

9 Process beheer


1 In- en uitloggen

UNIX is een multi-user systeem. Dat wil zeggen dat meerdere gebruikers tegelijkertijd op de zelfde computer kunnen werken. Iedere gebruiker heeft daarbij zijn eigen stukje geheugenruimte in gebruik. Het is dus logisch dat de computer moet weten wie (welke gebruiker) op een bepaald moment een commando geeft. Daarom moet je voordat je met een UNIX systeem kunt werken, eerst kenbaar maken wie je bent. We noemen dit inloggen.

1.1 In loggen.

Iedere gebruiker van een UNIX systeem heeft een eigen naam. Vaak is dit de voornaam van de eigenlijke gebruiker maar dat hoeft niet. Het kan ook een afkorting, initialen of iets willekeurigs zijn. Het is de gebruikers identificatie (in vaktermen: userid) waaronder je in het systeem bekend bent. Wanneer je met een UNIX systeem wilt gaan werken, moet je er eerst voor zorgen dat je van de systeembeheerder een userid krijgt. Daarna kun je inloggen. We zullen het inloggen nu stap voor stap doornemen.

  1. Login prompt

    Wanneer je de terminal aanzet, geeft het systeem de login prompt. Dit is een boodschap van de computer die aangeeft dat een gebruiker in kan loggen. In sommige systemen kan dit een heel verhaal zijn maar waar het op neer komt is dat het altijd eindigt met de tekst login: Krijg je de login prompt niet te zien, dan zal meestal een paar keer op RETURN drukken de login prompt wel te voorschijn brengen.

  2. userid intypen

    Als antwoord op de login prompt typ je nu je userid in gevolgd door de RETURN toets. Let er wel op dat hoofdletters en kleine letter niet hetzelfde zijn. Dus: de userid Jan is iets anders dan de userid jan .

  3. Password prompt

    Als je een wachtwoord (in vaktermen: password) hebt, zal het systeem hier om vragen door de password prompt op het scherm te laten zien:

    Password:
    
    Er wordt dan verwacht dat je je password intypt.

  4. Password intypen

    Typ nu achter de password prompt je password in en sluit dit weer af met de RETURN toets. Een password is een geheim woord wat alleen de gebruiker van dat password kent. Dit is een beveiliging tegen ongeoorloofde toegang tot het systeem. Iemand die geen password heeft kan niet inloggen en dus ook het systeem niet gebruiken. Wanneer je het password intypt, wordt het niet op het scherm weergegeven. Je kunt dus niet zien wat je doet. Dat is maar goed ook want het is natuurlijk niet de bedoeling dat iemand die over je schouder mee kijkt je password te zien krijgt. Maak je bij het intypen van je password een vergissing, geen paniek; probeer het gewoon nog een keer.

  5. Shell prompt

    Als alles goed gegaan is en je wordt door het systeem geaccepteerd, dan komen er een flink aantal boodschappen over het scherm rollen. Dit zijn mededelingen van het systeem en van de systeembeheerder. Voorlopig zullen we dat maar even laten voor wat het is. Als laatste van al die tekst verschijnt de shell prompt.

Hieronder is een voorbeeld gegeven van het login-gebeuren:


Red Hat Linux release 7.3 (Valhalla)
Kernel 2.4.18-3 on an i686

kithira login: arjen
Password:
Last login: Tue Oct  1 08:59:22 on tty1
[arjen@kithira arjen]$

Op de laatste regel staat [arjen@kithira arjen]$. Dit is de shell prompt. De computer geeft hier mee aan dat een commando ingetypt kan worden. Soms ziet de shell prompt er wat ingewikkeld uit. Laat je hierdoor in het begin niet afschrikken.

1.2 Password veranderen

Als je voor de eerste keer op een UNIX systeem inlogt, moet je om te beginnen je password veranderen. Afhankelijk van wat de systeem beheerder voor je heeft geregeld zal je nog geen password hebben of eentje die te eenvoudig is (bij voorbeeld hetzelfde als je userid). Je moet er nu voor zorgen dat je jezelf een password geeft wat je zelf gemakkelijk kan onthouden maar waar iemand anders niet zo snel op zal komen. Je kunt je password op ieder willekeurig moment wijzigen als je dat wilt, maar eerst gaan we het even oefenen. Typ achter de shell prompt het commando passwd. Je krijgt dan het volgende te zien:

[arjen@kithira arjen]$ passwd
passwd:  Changing password for arjen
(current) UNIX password:

Heb je al een password, dan moet je dat hier ingeven. Geef je het juiste password dan kun je een nieuw password intypen. Het systeem vraagt hier om met de prompt:

New UNIX password:

Type nu test 123 en sluit af met RETURN. Uiteraard is dit nieuwe password weer niet op het scherm te zien. Je krijgt nu weer een prompt te zien:

Retype new UNIX password:
Type nu weer test 123, gevolgd door RETURN. Er wordt nu gecontroleerd of je beide keren hetzelfde hebt ingetypt. Is dat niet zo, dan heb je dus in een van beide een typefout gemaakt en weet je dus niet zeker wat het nieuwe password nu eigenlijk is. Het simpele edoch desastreuze gevolg is dat je niet meer kunt inloggen !

1.3 Uit loggen

Het laatste wat moet gebeuren als je klaar bent achter een UNIX systeem is uitloggen. Dit is een uitermate belangrijke handeling omdat een ander je werk kan vernietigen wanneer je niet uitlogt. Uit loggen doe je in de regel door het commando exit in te typen. Ook control-D (de D toets indrukken terwijl je de 'Ctrl'-toets vast houdt) kan hetzelfde effekt hebben.

In sommige systemen, zoals die van Silicon Graphics moet je met de muis een menu'tje oproepen om uit te loggen. Hoe dan ook, zorg er voor dat je uitgelogd bent wanneer je weg gaat !

1.4 Oefeningen

  1. Waarom wordt het oude password gevraagd wanneer je je password gaat veranderen?
  2. Verander je password nogmaals. Type nu echter bij de prompt:
    Retype new UNIX password:
    
    iets anders in. Welke boodschap geeft het systeem ?
  3. Stel nu met behulp van passwd je definitieve password in. Zorg er voor dat je een password bedenkt wat je kan onthouden. Als je na een week terug komt en je password vergeten bent sta je behoorlijk voor aap.
  4. Log uit en log weer opnieuw in om je nieuwe password te testen.

2 Commandos

Een commando is een opdracht die via een shell aan het systeem gegeven wordt. In principe is ieder commando een regel welke door de gebruiker ingetypt wordt, afgesloten met een RETURN. De shell interpreteert het commando en tracht dit vervolgens uit te voeren. Alleen het eerste woord van zo'n regel is het eigenlijke commando; de eventuele rest van de regel zijn argumenten die op dat commando betrekking hebben.

Het merendeel van de commando's zijn in feite programma's welke op schijf zijn opgeslagen. Wordt bijvoorbeeld het commando ls ingevoerd, dan wordt het programma in de file /bin/ls uitgevoerd (geëxecuteerd). We zullen in dit hoodfstuk leren om commando's aan de computer te geven en informatie over de diverse commando's op te vragen.

2.1 Eenvoudige commando's

Laten we beginnen met een eenvoudig commando: date. Type het commando date achter de shell prompt. De datum en tijd verschijnen nu op het scherm:

[arjen@kithira arjen]$ date
Fri Jan 21 09:46:12 MET 1994
[arjen@kithira arjen]$
Op de regel na de datum en tijd verschijnt weer een nieuwe shell prompt. Het systeem is weer klaar voor een volgend commando. Laten we nu eens een kalender op het scherm zetten. Hiervoor is het commando cal, bij voorbeeld:
[arjen@kithira arjen]$ cal
   January 1994
 S  M Tu  W Th  F  S
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
[arjen@kithira arjen]$
Je ziet dan een kalender voor deze maand. Het is ook mogelijk om met cal een kalender van een andere maand te laten zien. Hiervoor moeten er argumenten aan het commando toegevoegd worden. Argumenten zijn extra woorden die achter het commando op dezelfde regel toegevoegd worden. Argumenten worden van elkaar en van het commando gescheiden door spaties. Geef nu het commando
   cal 4 1994
Je ziet dan de kalender van de vierde maand (april) van 1994. Wat de argumenten betekenen hangt helemaal van het commando zelf af. In het geval van cal bij voorbeeld, wordt het eerste argument, dus het tweede woord op de commando regel, gezien als het nummer van een maand (1=januari, 2=februari, etc.). Het tweede argument wordt door cal geïnterpreteerd als een jaartal. De algemene vorm van cal is dus:

cal maand jaar

Let op de cursief gedrukte woorden. Deze moet je niet letterlijk overtypen maar betekenen dat je daar iets anders voor in moet vullen. In dit geval dus twee getallen.

De maand mag in het cal commando weggelaten worden. Als cal maar één argument krijgt, wordt de kalender van dat gehele jaar op het scherm gepresenteerd. Probeer eens:

   cal 1994

Een computer is in feite een grote rekenmachine. Het zou dan ook te gek zijn als je, achter een computer zittend, een klein rekenmachientje bij je zou moeten hebben om een paar simpele berekeningen te maken. Gelukkig hoeft dat niet. In een UNIX systeem is een programma aanwezig waarmee je dit kunt doen: bc. Type nu:

   bc
uiteraard gevolgd door een RETURN. Je merkt dan dat de shell prompt verdwijnt; dit komt omdat bc wacht op invoer vanaf het toetsenbord. Je kunt nu allerlei berekeningen intypen. Type bijvoorbeeld
   2 + 2
bc geeft het antwoord en wacht weer op een volgende berekening. Hier is een voorbeeld:
   [arjen@kithira arjen]$ bc
   2 + 2
   4
   37 * 3
   111
   3 ^ 4
   81
   5 + 6 * 3
   23
bc is dus niet het soort commando wat zijn werk af maakt en je weer terug laat keren naar de shell. Je blijft in het programma bc totdat je quit intypt. De shell prompt komt dan weer terug, aangezien bc gestopt is. quit is dus een commando wat door bc begrepen wordt; het is dus geen commando voor de shell. Een vergissing die veel beginnende gebruikers maken is het geven van commando's voor de shell terwijl er een ander programma draait. Let er altijd op dat je de shell prompt ziet alvorens een commando aan de shell te geven.

2.2 De ingebouwde handleiding

Als je het een en ander wilt weten over een bepaald commando, dan is de handleiding altijd nabij. In UNIX zit de handleiding ofwel manual namelijk ingebouwd. Geef bij voorbeeld het commando man cal om de handleiding of manual page van cal op het scherm te zetten:


[arjen@kithira arjen]$ man cal



cal(1)                   USER COMMANDS                     cal(1)



NAME
     cal - print calendar

SYNOPSIS
     cal [ [ month ] year ]

DESCRIPTION
     cal prints a calendar for the specified year.  If a month is
     also  specified,  a calendar just for that month is printed.
     If neither is specified, a calendar for the present month is
     printed.   The month is a number between 1 and 12.  The year
     can be between 1 and 9999.  The calendar  produced  is  that
     for England and the United States.

NOTES
--More--(56%)
De prompt --More--(56%) onderaan het scherm laat zien dat er nog meer te zien is van de handleiding van cal. Met een druk op de spatiebalk komt de volgende pagina tevoorschijn. man is ook weer zo'n commando wat niet onmiddelijk naar de shell terugkeert. Pas als de laatste pagina van de handleiding over het scherm gerold is verschijnt de shell prompt weer. Behalve de spatie balk hebben ook een aantal andere toetsen een betekenis. De belangrijkste zijn: Zoals inmiddels waarschijnlijk al duidelijk is, verwacht man een argument: het commando waar de manual page voor opgevraagd wordt. In het algemeen ziet man er dus zo uit:

man commando

Om de manual page van het passwd commando wat we in het vorige hoofdstuk gebruikt hebben, op te vragen, type je dus:
   man passwd

De layout van de manual pages zelf, met andere woorden de manier waarop ze opgebouwd zijn, is vrij uniform. Hierdoor is de toegankelijkheid van de manual pages sterk vergroot. Op iedere manual page zijn de paragrafen in een min of meer vaste volgorde gerangschikt. Bovendien zijn er een aantal paragrafen die in vrijwel iedere manual page aanwezig zijn. Deze indeling in paragrafen met duidelijke kopteksten heeft tot gevolg dat de gezochte informatie snel en gemakkelijk terug te vinden is. De paragrafen die in iedere manual page terug keren zijn:

Er zijn verder een aantal paragrafen die niet bij ieder item voor komen, maar alleen daar waar ze relevant of nuttig zijn. Zo zijn er bij commando's die een aantal opties kennen een aparte paragraaf opgenomen voor die opties, OPTIONS genaamd. Ook worden soms enkele voorbeelden gegeven onder EXAMPLES. Veel items maken gebruik van speciale files. Deze files zijn dan opgesomd onder de kop FILES. Andere veel voorkomende paragrafen zijn SEE ALSO welke verwijzingen bevat naar andere, gerelateerde items, DIAGNOSTICS, waarin beschreven is op welke manier een item uitzonderings situaties en fouten afhandelt en BUGS, waarin de foutjes of minder perfekte eigenschappen van het item beschreven zijn.

2.3 Oefeningen

  1. Op welke dag van de week ben je dit jaar jarig ?
  2. Bestudeer de manual page van cal. Wat was er in september 1752 aan de hand ?
  3. Ook man heeft een manual page. Bestudeer deze eens.

3 Files

Om op een zinnige manier met een computer te kunnen werken, zullen er eerst gegevens in gestopt moeten worden. Alle gegevens die in een compter systeem aanwezig zijn, zijn opgeborgen in de vorm van files (bestanden). Of het nu gaat om documenten, zoals dit diktaat, programma's zoals cal, databases, plaatjes, modellen of wat dan ook, het is allemaal opgeslagen in files. Het is dan ook niet zo verbazingwekkend dat het beheren van die files een uitermate belangrijke bezigheid is. Iedere gebruiker is verantwoordelijk voor een goed beheer van zijn eigen files.

In dit hoofdstuk zullen we leren hoe files aangemaakt, bekeken, gekopieerd en verwijderd kunnen worden.

3.1 Files aanmaken

Er zijn veel manieren om een file te creëren. Veel programma's produceren uitvoer welke tot nu toe naar het scherm is gestuurd. In plaats van naar het scherm kan de uitvoer van de meeste programma's ook naar een file gestuurd worden. Iedere file in het systeem wordt geïdentificeerd met een naam. De naam van een file wordt bedacht door de gebruiker die de file aanmaakt. Laten we eens een nieuwe file maken met cal.

% cal 1994 >kalender94
%
Met het 'groter-dan' teken wordt de uitvoer die normaliter naar het scherm zou gaan naar een file gestuurd. Er wordt dus niets op het scherm getoond. Je hebt nu dus een file met de naam kalender94 gecreëerd.

3.2 Files bekijken

Om te bekijken welke files je hebt of om meer informatie te verkrijgen over een bepaalde file kan het ls (LiSt) commando gebruikt worden. In zijn eenvoudigste vorm laat ls de de namen van de files zien, alfabetisch gesorteerd. Wordt er een filenaam aan ls als argument meegegeven, dan wordt alleen de naam van deze file afgedrukt als die file aanwezig is. Kijk met ls of de file die je net hebt aangemaakt inderdaad aanwezig is:

% ls
kalender94
%

Je kunt aan ls ook argumenten meegeven. Veel van die argumenten zijn opties die de uitvoer van ls beïnvloeden. ls kent een enorm aantal opties (22 in de System-V uitvoering). Kijk maar eens in de manual page. Je ziet dat alle opties met een min-teken ('-') beginnen. Argumenten die niet met een min-teken beginnen zijn in de regel namen van files. Dit is niet altijd zo, maar voor de meeste commando's gaat het wel op. de betekenins van de opties is natuurlijk wel voor elk commando verschillend. Met de -l optie is meer informatie over de files te verkrijgen. Type het commando:

% ls -l
total 4
-rw-r--r--   1 arjen    develop     1721 Jan 27 11:22 kalender94
%
Je ziet dan voor de naam kalender94 een aantal gegevens staan. De regel begint met de permissie vlaggen. Deze geven o.a. aan wie de file mogen lezen en wie in de file mogen schrijven. Een stukje verderop staan twee namen: arjen en develop. Dit zijn de eigenaar van de file en de groep van gebruikers waar de file toe behoort. Na de groep volgt de grootte van de file in bytes. In dit voorbeeld beslaat de file kalender94 1721 bytes. Als laatste staan voor de naam van de file de datum en de tijd waarop de file voor de laatste keer veranderd is. Is de file één keer aangemaakt en daarna nooit meer veranderd, dan is dit natuurlijk het aanmaaktijdstip

Niet alle files worden zichtbaar gemaakt met ls. Files waarvan de naam begint met een punt ('.') zijn zogenaamde verborgen ('hidden') files. Deze files worden alleen getoond als de -a optie aan ls meegegeven wordt. Twee van deze hidden files zijn altijd aanwezig. Dit zijn "." en ".." welke staan voor de huidige en bovenliggende directory. De betekenis heirvan komt in het volgende hoofdstuk aan de orde.

Het commando cat is verreweg de eenvoudigste methode om files op het scherm weer te geven. De naam cat staat voor 'conCATenate'. Dit houdt in dat het commando

cat file...

alle genoemde files achter elkaar in de aangegeven volgorde leest en uitvoert naar het scherm. Geef, om de inhoud van de kalender file te lezen het commando:
   cat kalender94
De kalender rolt dan zonder te stoppen over het scherm. Dat is op zijn zachtst gezegd een beetje onoverzichtelijk. Is een file nogal groot en je wilt de inhoud op je gemak kunnen lezen, dan is het beter om more te gebruiken om de file op het scherm te laten zien. Type het commando:
   more kalender94
De eerste helft van de kalender komt dan op het scherm. Je hebt nu de tijd om dit op je gemak te lezen. heb je alles gezien, dan druk je op de spatiebalk om de tweede helft van de kalender op het scherm te zetten.

more is een filter wat de inhoud van een (text) file scherm voor scherm op een terminal laat zien. Telkens wanneer een scherm is weergegeven, verschijnt op de onderste regel --More-- en wacht more op invoer vanaf het toetsenbord. Op dat moment is een veelheid van commando's mogelijk. De eenvoudigste zijn een RETURN om één regel verder te gaan, een SPATIE om een geheel scherm verder te gaan of een 'q' om te stoppen. Met het 'h' (van help) commando krijg je een overzicht van alle commando's die more kent. Hierbij wordt opgemerkt een ingetypt commando onmiddellijk uitgevoerd wordt. Het is dus niet nodig ieder commando af te sluiten met een RETURN. Bovendien worden ingetypte commando's niet op de terminal ge-echoed. Een uitzondering hierop zijn de ! en / commando's. Merk op dat more op dezelfde manier werkt als man. In feite is het ook precies hetzelfde want man maakt gewoonweg gebruik van more om manual pages op het scherm te tonen.

Soms wil je alleen maat de eerste regels of alleen de laatste regels van een file op het scherm zien. Hiervoor zijn de commando's head en tail ('kop' en 'staart') te gebruiken. Met head worden de eerste 10 regels van een file op het scherm gezet; met tail de laatste 10 regels. Probeer nu met head de eerste 3 maanden van de kalender op het scherm te zetten:

% head kalender94



                                1994

         Jan                    Feb                    Mar
 S  M Tu  W Th  F  S    S  M Tu  W Th  F  S    S  M Tu  W Th  F  S
                   1          1  2  3  4  5          1  2  3  4  5
 2  3  4  5  6  7  8    6  7  8  9 10 11 12    6  7  8  9 10 11 12
 9 10 11 12 13 14 15   13 14 15 16 17 18 19   13 14 15 16 17 18 19
%
Je ziet dat het net niet lukt. Er zijn zeker drie extra regels nodig om de eerste drie maanden volledig op het scherm te krijgen. Hiervoor kent head de optie -aantal. De eerste aantal regels worden dan op het scherm gezet. We proberen nu de eerste 13 regels:
% head -13 kalender94



                                1994

         Jan                    Feb                    Mar
 S  M Tu  W Th  F  S    S  M Tu  W Th  F  S    S  M Tu  W Th  F  S
                   1          1  2  3  4  5          1  2  3  4  5
 2  3  4  5  6  7  8    6  7  8  9 10 11 12    6  7  8  9 10 11 12
 9 10 11 12 13 14 15   13 14 15 16 17 18 19   13 14 15 16 17 18 19
16 17 18 19 20 21 22   20 21 22 23 24 25 26   20 21 22 23 24 25 26
23 24 25 26 27 28 29   27 28                  27 28 29 30 31
30 31
%
Met tail kunnen we precies hetzelfde uithalen. Laat nu de laatste drie maanden van de kalender zien met
   tail -11 kalender94
De volgende figuur geeft een overzicht van de commando's om een file op verschillende manieren op het scherm te presenteren:

3.3 Operaties op files

Het komt vaak voor dat je van een file een kopie wilt maken. Bij voorbeeld als je de inhoud van een file wilt veranderen maar de originele file wilt bewaren. Maak nu een kopie van de file kalender94 met het commando:

% cp kalender94 ditjaar
%
Zoals je met ls kunt zien, heb je nu dus twee files, kalender94 en ditjaar. De inhoud van die files is identiek. Met andere woorden, ditjaar is een kopie van kalender94. Een file kan dus gekopiëerd worden door middel van het cp (CoPy) commando. Het commando
cp oude_file nieuwe_file
maakt een kopie van oude_file en geeft de kopie de naam nieuwe_file. Het spreekt vanzelf dat de originele file oude_file wel moet bestaan. Is dit niet het geval, dan geeft cp een foutmelding:
 cp: oude_file: No such file or directory
Als er al een file met de naam nieuwe_file bestaat voordat het cp commando gegeven wordt, wordt de originele inhoud van deze file vernietigd en vervangen door de inhoud van oude_file. Er verschijnt dan geen waarschuwing op het scherm! Het enige wat in dit geval wel bewaard wordt zijn de eigenaar en de mode van nieuwe_file. Als de file met naam nieuwe_file niet bestond, wordt er een nieuwe file aangemaakt om de kopie in op te bergen.

Een laatste opmerking: Een file kopiëren naar zichzelf is in principe nutteloos. cp zal dit dan ook weigeren. Bij voorbeeld op het commando:

 cp textfile textfile
wordt gereageerd met de foutmelding:
 cp: textfile and textfile are identical (not copied).

Het is ook mogelijk om een file een andere naam te geven zonder dat er daadwerkelijk een kopie van de file gemaakt wordt. De file wordt als het ware verplaatst naar een file met een andere naam. Om een file te verplaatsen wordt het mv (MoVe) commando gebruikt. Geef de file ditjaar de naam jaarkalender door middel van het commando:

% mv ditjaar jaarkalender
%
Kontroleer de uitwerking met ls. De naam ditjaar is verdwenen en is vervangen door de naam jaarkalender. De algemene vorm van mv is dus
mv oude_naam nieuwe_naam
Dit heeft tot gevolg dat de naam van de file oude_naam verandert in nieuwe_naam. Als een file met de naam nieuwe_naam reeds bestaat wordt deze eerst verwijderd, voordat oude_naam verplaatst wordt. De inhoud van de file oude_naam wordt dus vernietigd !

Als je een file niet meer nodig hebt, kun je die file verwijderen. Laten we nu de kopie van de kalender weg halen:

% rm jaarkalender
%
Kontroleer met ls of de file jaarkalender inderdaad verdwenen is.

Met rm (ReMove) kun je dus file verwijderen. De algemene vorm van rm is:

rm file...
De "..." achter file betekent dat je één of meer files als argumenten achter rm kan plaatsen. Alle genoemde files worden dan verwijderd. Let wel: een file die met rm weggegooid is, is ook echt verdwenen. Een eenmaal verwijderde file is op geen enkele manier meer terug te halen. Gooi je een file per ongeluk weg dan heb dus gewoon pech ! Om jezelf enigzins hiertegen te beschermen kun je de -i optie (van Interaktief) aan rm meegeven. In dat geval vraagt rm voor iedere file of die wel verwijderd moet worden. Hier is een voorbeeld:
% rm -i jaarkalender
rm: remove  jaarkalender: (y/n)? n
%

3.4 Wildcards

Veel van de hierboven besproken commando's voeren bewerkingen uit op één of meer files. Als er een lange lijst van file namen aan zo'n commando meegegeven moet worden, brengt dat nogal wat typewerk met zich mee. Gelukkiger is er een handiger manier om een grote hoeveelheid filenamen te specificeren, en wel met wildcards. Een wildcard is een speciaal teken waarmee je de opdracht geeft om naar bepaalde filenamen te zoeken. In dit hoofdstuk zullen we er twee behandelen:

Deze wildcards kun je op iedere willekeurige plaats in een argument gebruiken. Geef je het commando:
% cat hoof*

dan komen alle files waarvan de naam begint met "hoof" achter elkaar over het scherm rollen. Geef je als argument alleen een sterretje, dan worden dus alle files gebruikt. Denk dan ook drie maal na voor je één keer het commando
rm *
geeft ! Je gooit al je files dan in één klap weg.

3.5 Oefeningen

  1. Met ls worden de files alphabethisch gesorteerd op het scherm gezet. Het is echter ook mogelijk om de files op datum en tijd te sorteren. Maak een lijst van je files in chronolische volgorde en in omgekeerd chronologische volgorde. Gebruik de -l optie om de uitvoer te controleren.
  2. Je kunt in een of meer files naar een woord zoeken door middel van het commando grep. Bestudeer de manual page van dit commando.

4 Directories

In het vorige hoofdstuk heb je gezien dat alle gegevens zijn opgeslagen in files. Zo'n file spreek je aan met zijn naam. Natuurlijk moet het systeem dan die naam kunnen terugvinden en de daarbij behorende inhoud van de file opzoeken. Dit gebeurt door een soort inhouds-opgave van alle files in een speciaal soort file te zetten. In die inhouds-opgave staan de namen van alle files, samen met een verwijzing naar de werkelijke inhoud van elk van die files. Dit is dus eigenlijk net zoiets als de inhouds-opgave van een boek, waar de titels van de hoofdstukken en de pagina waar ieder hoofdstuk begint staat afgedrukt. Zo'n inhoudsopgave wordt een directory genoemd. Een directory is dus niets anders dan een file die namen van andere files bevat. Deze files kunnen op zichzelf ook weer directories zijn.

Het belang van de indeling van files in directories is twee\o'e"'rlei. In de eerste plaats is een directory een inhoudsopgave van de files die op de schijf aanwezig zijn. Voor iedere file is er een stukje in de directory gereserveerd (de 'directory-entry'). De directory-entry bevat behalve de naam van de file ook informatie over de plaats waar de file op de schijf fysiek te vinden is, hoe lang de file is, op welke tijd de file gecreerd is, etc. Het operating system heeft dus de directory nodig om files te kunnen vinden. Als een file wel bestaat maar zijn directory-entry is verdwenen, dan is de informatie in die file nutteloos omdat niets of niemand deze informatie meer kan teruglezen. In sommige (oude) operating systems zoals CP/M is een directory niet meer dan dat: een inhoudsopgave van de disk.

Het is dus theoretisch mogelijk om alle files onder één en dezelfde directory te plaatsen. Dit stuit echter op grote praktische bezwaren. Naarmate het aantal files en dus ook het aantal soorten files toeneemt zal de warboel steeds moeilijker te overzien zijn. Zelfs voor het kleinste UNIX systeem zou een dergelijke opzet niet te overzien, laat staan te beheersen zijn. Daarom worden de (naar gebruik) bij elkaar behorende files in een directory gegroepeerd. Vaak wordt dit vergeleken met een opbergsysteem van documenten. Verschillende documenten (files) die bij elkaar behoren worden opgeborgen in een map (directory). Bij elkaar behorende mappen kunnen weer samen opgeborgen in een grotere map. In sommige operating systems wordt een directory dan ook wel een map ('folder') genoemd.

Een bijkomend voordeel van de indeling van files in directories is de bescherming. Een gebruiker (of de systeem beheerder) kan specificeren dat een directory niet toegankelijk is voor andere gebruikers. Alle files en (sub)directories hierin zijn dan beschermd tegen het ongeauthoriseerd lezen of wijzigen door anderen. Bovendien kan het voorkomen dat een (wat minder ervaren) gebruiker alle files weg gooit met "rm *". Als dit zou gebeuren wanneer alle files in de root directory zouden staan zou het gehele file system gewist zijn. Nu blijft de schade beperkt tot die ene directory.

4.1 De directory boom

Files zijn dus gegroepeerd in directories. Deze directories kunnen op hun beurt weer (sub)directories bevatten. Op die manier ontstaat een boomstructuur van directories. De structuur van een file system zou er dan als volgt uit kunnen zien:

Een dergelijke structuur wordt een 'boom' structuur genoemd. Merk overigens op dat de boom ondersteboven getekend wordt. Bovenaan is de wortel van de boom te zien. In UNIX termen heet deze dan ook de root. Alle andere directories en files zijn dus vanuit de root te bereiken. Om een file ergens willekeurig in de directory boom aan te spreken is het dus niet voldoende om alleen de naam van de file te geven. Je moet bovendien aangeven in welke directory de file zich bevindt. Dit gebeurt door de naam van de file vooraf te laten gaan door de namen van de directories die je moet doorlopen om bij de file te komen. De namen van de directories worden gescheiden door een slash ('/'). De naam
   /unix
is dus de naam van de file unix in de root directory. De eesrte '/' betekent dat de naam in de root directory begonnen wordt. De naam
   /usr/lib/X11/bitmaps/stones
is dus de file stones in de directory bitmaps. Deze directory staat weer onder de directory X11, die weer in de directory lib in de directory usr staat. Om de file te vinden moet het systeem eerst de directory usr in de root directory opzoeken en dan achtereenvolgens de directories lib, X11 en bitmaps doorlopen om tenslotte bij de file stones aan te komen. Zo'n filenaam met alle directories er bij geeft dus aan welk pad er doorlopen moet worden om bij de uiteindelijk bedoelde file te komen. Een dergelijke filenaam heet dan ook wel een pathname.

Wanneer een pathname begint met een slash ('/') dan start het zoeken naar de file altijd in de root directory. De naam van de root directory is dan ook /. De pathname is dus een absolute pathname. Het kan ook anders. Je zit namelijk zelf (d.w.z. de shell) ook altijd in een directory: de huidige directory. Als je een filenaam intypt zonder path, wordt hiermee de file in de huidige directory bedoeld. Meer algemeen gezegd, als een pathname niet begint met een '/' dan wordt de file gezocht vanaf de huidige directory. We spreken in dat geval van een relative pathname. De pathname is dus relatief ten opzichte van de huidige directory. Zit je bijvoorbeeld in de directory

   /usr/lib
dan wordt met de relatieve pathname
   X11/bitmaps/stones
de zelfde file aangeduid als met de absolute pathname in het vorige voorbeeld.

De huidige directory ('working directory') waar je op dit moment zit kan op het scherm getoond worden door middel van het commando pwd. Dit laat de absolute pathname van de huidige directory zien. Geef het commando pwd om te zien in welke directory je nu zit. Het resultaat kan bij voorbeeld het volgende zijn:

% pwd
/home/arjen
%

Iedere gebruiker heeft zijn eigen directory waar hij of zij files in kan opslaan. Dit is de HOME directory van die gebruiker. Wanneer je in logt kom je direkt in je HOME directory terecht. Natuurlijk kun je in je HOME directory weer subdirectories maken om files op een overzichtelijke manier op te bergen. Twee 'subdirectories' die altijd in iedere directory aanwezig zijn, zijn de . en .. directories. Normaal gesproken zijn ze met ls niet te zien, maar als je de -a optie gebruikt worden ze op het scherm getoond:

% ls -al
total 12
drwxr-xr-x   2 arjen    develop      512 Feb  1 09:31 .
drwxr-xr-x   3 arjen    develop     1024 Feb  2 10:47 ..
-rw-r--r--   1 arjen    develop     1721 Feb  1 09:31 jaarkalender
-rw-r--r--   1 arjen    develop     1721 Jan 27 11:22 kalender94
%
Aan de 'd' helemaal vooraan in de regel kun je herkennen dat het directories zijn. De directory "." is de huidige directory. Wanneer een commando vereist dat je als argument de naam van een directory geeft, kun je met "." de huidige directory aanduiden. De directory ".." is de directory die juist boven de huidige directory ligt.

Je kunt door de gehele directory boom heen stappen, dat wil zeggen, je huidige directory veranderen door het commando cd, wat staat voor 'Change Directory'. Aan cd kan de naam van de nieuwe directory als argument meegegeven worden. Natuurlijk kun je zowel een absolute als een relatieve pathname gebruiken. Wordt cd zonder argumenten gebruikt, dan keer je terug naar je HOME directory. Geef je .. als argument aan cd, dan ga je naar de directory die één directory hoger in de boom ligt dan de huidige directory. Met andere woorden, je stapt een directory omhoog. We zullen dit demonstreren aan de hand van de volgdende voorbeeld directory-boom:

Controleer met pwd na ieder commando in welke directory je zit. Geef het commando:
% cd
%
Je weet nu zeker dat je in je HOME directory zit, ongeacht waar je eerst was. Ga nu een directory omhoog:
% cd ..
%
Je bent nu in de directory waar de home directories van alle gebruikers onder hangen. Een van die gebruikers is 'arjen'. Ga nu naar deze home directory met:
% cd arjen
%
Je kunt ook meerdere directories tegelijk naar beneden gaan. Je geeft dan gewoon de volledige (relative) pathname van de directory op. Ga nu twee directories dieper met:
% cd src/aim
%
Dit kan natuurlijk ook met een absolute pathname:
% cd /home/arjen/src
%
Door gebruik te maken van de ".." directory kun je in \o"e'"\o"e'"n commando omhoog en direkt weer naar beneden springen. Je kunt zelfs meerdere directories tegelijk omhoog gaan door het gewenste aantal ".." directories in de pathname op te nemen:
% cd ../../naam
%
Vul voor naam de naam van je eigen home directory in. Je bent nu weer terug waar je begonnen was.

4.2 Maken van directories

Nieuwe directories kunnen gecreëerd worden met mkdir (MaKe DIRectory). Aan mkdir worden één of meer namen van de nieuwe directories als argumenten meegegeven. Automatisch worden in elke nieuwe directory twee directory-entries aangemaakt: "." en "..". Maak nu een nieuwe directory met de naam agenda door het commando

mkdir agenda
te geven. Controleer met ls of die directory inderdaad is aangemaakt en of de "." en ".." entries aanwezig zijn. Kopieer nu de kalender files kalender94 en jaarkalender naar de diretcory agenda:
% cp kalender94 jaarkalender agenda
%
Hiervoor moet je een tweede vorm van cp gebruiken, namelijk de vorm die meerdere files naar een directory copieert.
cp file1 file2 file3 ... directory
De gecopiëerde files krijgen de zelfde naam als hun overeenkomstige originelen. Het spreekt bijna vanzelf dat in deze vorm het laatste argument een directory moet zijn. Is het laatste argument geen directory, dan betekent dit niet dat de genoemde files naar de huidige directory gecopieerd moeten worden zoals b.v. in MS-DOS het geval is. cp geeft dan de volgende foutmelding:
cp: Target must be directory
Usage: cp [-i] [-p] f1 f2
       cp [-i] [-p] f1 ... fn d1
       cp [-i] [-p] [-r] d1 d2
Is een van de genoemde files een directory, dan wordt deze niet gecopieerd, tenzij de -r optie gespecificeerd is (zie verderop).

Met mv kunnen we iets dergelijks doen. Op dezelfde manier als met cp kunnen we meerdere files tegelijkertijd naar een andere directory verplaatsen. De directory waar de files naar toe verplaatst worden moet uiteraard wel bestaan. De algemene vorm van deze variant van mv is:

mv filenaam... dirnaam... directory
In deze vorm is het laatste argument altijd een directory die reeds bestaat. De voorgaande argumenten mogen files of directories zijn (een willekeurig aantal en in willekeurige volgorde). Alle genoemde files worden verplaatst naar de directory directory. Maak, om dit te oefenen eerst drie files aan met behulp van cal:
% cal 1 1994 >jan.94
% cal 2 1994 >feb.94
% cal 3 1994 >maa.94
%
Maak nu een nieuwe directory kalenders en verplaats de drie kalender files naar deze directory. Er blijven dus geen kopieën van de kalender files jan.94, feb.94 en maa.94 achter in de huidige directory.
% mkdir kalenders
% mv *.94 kalenders
%
Controleer steeds met ls of er inderdaad gebeurt wat je bedoeld hebt.

We gaan nu de directory kalenders met zijn complete inhoud kopiëren naar de directory agenda. Zoals we in het vorige hoofdstuk hebben gezien, is het niet zonder meer mogelijk om met cp directories te kopiëren. Je moet cp expliciet vertellen dat een directory met inhoud recursief naar een andere directory gekopiëerd moet worden. Dit doe je door de -r optie als argument aan cp mee te geven:

% cp -r kalenders agenda
%
De -r optie kan alleen bij de tweede vorm gebruikt worden. Als cp dan een directory tussen de te kopiëren files tegenkomt, wordt de gehele onderliggende directory boom mee gekopiëerd. Een waarschuwing is hierbij echter wel op zijn plaats. Als de directory waar naartoe gekopiëerd wordt deel uitmaakt van de te kopiëren directory boom, zal cp files blijven kopiëren totdat de gehele schijf vol is.

4.3 Overzicht van directories

Je hebt inmiddels een aardige directory boom aangemaakt. Om nu een overzicht te krijgen van de hele directory structuur en bovendien te zien hoeveel ruimte ieder stuk van de directory boom in beslag neemt, kun je du (Disk Usage) gebruiken:

% du
8       ./agenda/kalenders
18      ./agenda
8       ./kalenders
36      .
%
du geeft een opsomming van het aantal blokken wat door files en directories op de disk in gebruik genomen wordt. In de regel is een blok een halve kilobyte (512 bytes). Aan du kan de naam van een file of directory meegegeven worden. De opsomming wordt dan gemaakt voor die file of directory. Ontbreekt de naam, dan wordt een opsomming gegeven voor "." (de huidige directory). Als de naam een directory is, wordt de gehele directory boom onder deze directory recursief afgelopen. Voor iedere subdirectory wordt dan het aantal gebruikte blokken gegeven.

du geeft aan hoeveel ruimte een directory in beslag neemt, maar zegt niets over de ruimte die nog op de schijf beschikbaar is om gegevens op te slaan. Om een overzicht te verkrijgen van de hoeveelheid gebruikte en vrije ruimte in de diverse file systems kan df gebruikt worden. Zonder argumenten geeft df van ieder file system hoeveel diskruimte er nog vrij is (in blokken van 512 bytes). Hier is een voorbeeld:

% df
/                  (/dev/dsk/c0d0s1 ):  143758 blocks   66140 files
/home              (/dev/dsk/c0d0s4 ): 1153066 blocks  344870 files
%
Je ziet hier twee file systems: "/", het root file system, en "/home", het file system voor de gebruikers. In dit voorbeeld zijn het twee aparte partities op een harde schijf. Van installatie tot installatie kan het aantal file systems sterk verschillen. Zo kunnen er bij voorbeeld meerdere schijven aanwezig zijn of file systems via een netwerk van andere machines aangesproken worden.

4.4 Verwijderen van directories

Net als voor files geldt ook voor directories dat je ze moet verwijderen als je ze niet meer nodig hebt. Om files op te ruimen ken je al het commando rm. Dit is echter niet te gebruiken om directories weg te halen. Probeer het maar:

% rm kalenders
rm: kalenders directory
%
rm protesteert dat kalenders een directory is en als zodanig dus niet verwijderd kan worden. Om directories weg te halen moet je een ander commando gebruiken, namelijk rmdir. De te verwijderen directories moeten dan wel leeg zijn. Dat wil zeggen, ze mogen geen files of subdirectories meer bevatten. Is een directory niet leeg wanneer je hem met rmdir probeert te verwijderen, krijg je een foutmelding:
% rmdir kalenders
rmdir: kalenders: Directory not empty
%
Je moet dus eerst alle files in de directory verwijderen en pas daarna de lege directory opruimen:
% cd kalenders
% rm *
% cd ..
% rmdir kalenders
%
Als de directory die je wilt verwijderen behalve files ook nog (sub)directies bevat zal dan al die directories op dezelfde manier moeten verwijderen. Gelukkig is er een snellere manier om dat te doen en wel door rm de -r optie (van Recursief) mee te geven. Wordt deze optie gespecificeerd, dan verwijdert rm niet alleen de genoemde directory maar ook (op recursieve wijze) de gehele boom van (sub)directories er onder. Je kunt dus de directory agenda inclusief de files die er in staan en de subdirectory kalenders met alle files die daar weer in staan in één slag opruimen door het commando:
% rm -r agenda
%
Let hier wel bij op dat de eenmaal verwijderde directories op geen enkele manier meer terug te halen zijn. Het is dus uitermate gevaarlijk om zonder eerst goed na te denken het commando
rm -r *
te geven.

4.5 Oefeningen

  1. Cp kent behalve -r nog twee opties. Wat doen deze ?
  2. Welke file systems zijn er aanwezig en hoeveel ruimte is er nog vrij ?
  3. Welk deel van de vrije ruimte kun jij gebruiken ?

5 vi

In ieder systeem worden tekst files gebruikt. Of het nu gaat om source code van programma's, documentatie, databases of andere gegevens, in veel gevallen wordt informatie in de vorm van leesbare tekst opgeslagen. De manier om dergelijke tekst files handmatig te creëren en aan te passen is zonder uitzondering met behulp van een tekst editor. Onder UNIX zijn standaard drie tekst editors beschikbaar: ed, ex, en vi. Vaak wordt hier als vierde editor edit aan toegevoegd. Deze is echter niet meer dan een beperktere versie van ex. Daarnaast hebben de meeste grafische werkstations nog de beschikking over grafisch georienteerde tekst editors. Een van de bekendste is xedit onder X Windows. Op Silicon Graphics machines is ook nog jot beschikbaar. Deze zijn stukken gemakkelijker in het gebruik maar hebben aanzienlijk minder mogelijkheden. Bovendien hebben deze grafische (muis-bestuurbare) editors nog een ander belangrijk nadeel. Je kunt ze alleen gebruiken als je achter het beeldscherm van het werkstation zelf zit. Ben je vanaf een andere plaats op het systeem ingelogd, bij voorbeeld via een netwerk, een 'gewone' terminal of vanaf thuis met een modem, dan is een grafische tekst editor absoluut onbruikbaar. Het enige wat je dan kunt doen is een 'ouderwetse' editor als vi of ex gebruiken. Voldoende reden dus om de moeite te nemen hier mee om te leren gaan. In het nu volgende zal de full-screen editor vi (uitspraak: 'vie-ai') behandeld worden en de line editor ex in beperkte mate.

Het zou te ver voeren vi in zijn geheel en tot in de kleinste details te beschrijven. Een aantal van de meer geavanceerde onderwerpen worden daarom niet behandeld. Enkele van deze onderwerpen zijn het instellen van de opties, terug halen van verloren gegane tekst, filteren van de tekst, macro's en afkortingen. Voor deze onderwerpen wordt verwezen naar de handleiding (man vi).

5.1 Commando's en invoer mode

Wat de onervaren vi gebruiker als eerste zal opvallen is het verschijnsel dat ingetypte letters niet in de tekst verschijnen. Na het opstarten komt vi namelijk in de commando mode terecht. Het aanslaan van een toets heeft dan in de meeste gevallen tot gevolg dat er een commando uitgevoerd wordt. Enkele van deze commando's (a, i, o, enz.) hebben tot gevolg dat vi overschakelt naar de invoer mode. In de invoer mode kan tekst in de file ingevoegd worden. Dan komen de ingetypte letters (en cijfers en leestekens) wél in de file terecht. Om weer terug te keren naar de commando mode dient de ESCAPE toets aangeslagen te worden. Indien de ESCAPE toets aangeslagen wordt terwijl vi reeds in de commando mode zit, geeft de terminal een piep of flitst het beeldscherm. Om dus zeker te stellen dat vi in de commando mode zit kan dus de ESCAPE toets een aantal keren aangeslagen worden, totdat de terminal piept. De ESCAPE toets kan dus ook gebruikt worden om een eventueel half ingetypt commando af te breken.

De commando's van vi bestaan meetal uit één enkele toets. In tegenstelling tot de shell behoeft een commando in vi niet afgesloten te worden met een RETURN. Het commando wordt direkt na het aanslaan van de toets uitgevoerd. Een uitzondering op deze regel vormen de commando's die met een dubbele punt (':') beginnen. Deze commando's hebben soms extra argumenten nodig en moeten dus wel met een RETURN afgesloten worden. Het onderstaande schema geeft de verschillende modi van vi weer.

Het eerste wat een gebruiker moet weten die een interaktief programma heeft opgestart is de manier om dat programma weer te verlaten zonder al te veel schade aan te richten. Om vi te verlaten wordt het commando :q (quit) gebruikt. Als er echter veranderingen zijn aangebracht in de file, zal vi dit commando weigeren. Vi geeft dan onderaan het scherm de boodschap
No write since last change (:quit! overrides)

Zoals deze melding al aan geeft is het mogelijk om vi dan toch te verlaten met het commando :q! In dat geval wordt een eventueel gewijzigde file niet opgeborgen en blijft het origineel behouden. Om de wijzigingen wel op te slaan, dient het commando :w (write) gebruikt te worden. De gewijzigde file wordt dan opgeborgen waardoor de oorspronkelijke file overschreven wordt. Er wordt dus geen kopie van de oorspronkelijke file bewaard.

Om de wijzigingen weg te schrijven alvorens vi te verlaten kan :x (exit) gebruikt worden. Als de file gewijzigd is, wordt deze weggeschreven. Is de file niet gewijzigd, dan gebeurt dit niet en wordt vi direkt verlaten. Een synoniem voor :x is ZZ. Dient alvorens vi te verlaten een ongewijzigde file toch weggeschreven te worden, dan kan dit met :wq. Dit is een combinatie van 'write' en 'quit'.

5.2 Door de file stappen

De vi editor heeft een aantal commando's om door de file te stappen. De meest bruikbare is waarschijnlijk het tegelijkertijd aanslaan van de CONTROL (of CTRL) toets en de 'D', hierna aangeduid met '^D'. Het commando ^D staat voor 'down'. Zoals deze naam reeds zegt wordt hierdoor naar beneden gestapt in de file, met als gevolg dat de tekst omhoog scrollt. Het aantal regels wat gescrolld wordt is normaal gesproken een half scherm en is dus afhankelijk van de grootte van de terminal (of window). Het tegenovergestelde van ^D is ^U ('up'). Hierdoor wordt dus het zelfde aantal regels in de file omhoog gescrolld. De tekst op het beeldscherm scrollt dus naar beneden. Het werkelijke aantal regels dat scrollt is in te stellen door ^D danwel ^U vooraf te laten gaan door een getal. Bij voorbeeld 12^D scrollt twaalf regels naar beneden. Daarna wordt bij iedere ^D of ^U twaalf regels gescrolld totdat er een ander aantal gespecificeerd wordt.

Om sneller door de file te stappen dan met ^D en ^U, kunnen ^F en ^B ('forward' en 'backward'). Met deze commando's wordt vrijwel een geheel scherm vooruit respectievelijk achteruit gesprongen. Er worden een paar regels in overlap tussen de verschillende schermen gehouden om zo het doorlezen te vergemakkelijken. De positie van de cursor wordt hierbij wel veranderd. De cursor komt namelijk op de eerste niet-blanko positie van de bovenste (^F) danwel de onderste (^B) regel terecht. Het schema hieronder geeft de vier scroll commando's weer:

De eenvoudigste manier om door het scherm te 'wandelen' is met de cursor besturings (pijltjes) toetsen. Deze toetsen doen precies wat ze zeggen; ze verplaatsen de cursor in de richting die het pijltje aan geeft. Dus het pijltje omhoog verplaatst de cursor naar de regel voor de huidige regel en het pijltje naar links verplaatst de cursor één positie naar links, etc. Als de cursor naar boven verplaatst wordt terwijl deze al op de bovenste regel van het scherm staat, scrollt de tekst een regel naar beneden om zo de regel boven de 'bovenste' regel zichtbaar te maken. Een soortgelijke aktie vindt plaats als er vanaf de onderste regel een regel naar beneden gegaan wordt.

Sommige, met name oudere terminals zijn niet uitgerust met cursor besturings toetsen. Om ook aan dergelijke terminals met vi te kunnen werken zijn er nog twee groepen andere toetsen beschikbaar om de cursor te besturen. De eerste groep bestaat uit vier toetsen die gewoonweg op een handige plaats op het normale toetsenbord liggen. Dit zijn h voor links, j voor naar beneden, k voor naar boven en l voor rechts. Ervaren vi gebruikers geven vaak aan deze toetsen de voorkeur omdat ze direkt onder hun vingers liggen. Een tweede alternatief voor de cursor besturing is de groep +, -, SPACE en BACKSPACE. SPACE is hierbij equivalent met l (naar rechts) en BACKSPACE met h (naar links). Met + wordt een regel verder gegaan, met ander woorden, de cursor gaat naar beneden. Het + commando is echter niet helemaal gelijk aan j. Als de cursor naar beneden gestuurd wordt met het pijltje of met j, blijft de horizontale positie op de regel behouden. Met + wordt naar het eerste niet-blanko karakter op de volgende regel gesprongen. De RETURN toets is in deze context equivalent aan de +. Voor de - toets geldt hetzelfde, maar dan in omgekeerde richting; deze stuurt de cursor een regel naar boven (vorige regel). De commando's voor cursor besturing staan in het onderstaande schema:

Er bestaat ook de mogelijkheid om direkt naar de bovenkant, het midden of de onderkant van het scherm te springen. De cursor springt in dat geval steeds naar het eerste niet-blanko karakter van de bedoelde regel. Met H (let wel: hoofdletter!) wordt naar de bovenkant van het scherm gesprongen. Zoals zoveel commando's in vi kan H vooraf gegaan worden door een getal. Dit getal geeft dan het aantal regels vanaf de bovenkant wat afgeteld wordt voor de sprong. Om een voorbeeld te geven: 6H springt naar de 6de regel. De tegenhanger van H is L. Deze zet de cursor op de onderste regel van het scherm. Ook L kan vooraf gegaan worden door een getal. In dit getal wordt het aantal regels vanaf de onderkant geteld. Met M wordt naar het midden van het scherm gesprongen. Als aan M een getal wordt meegegeven, wordt dit stilzwijgend genegeerd. Immers, vanaf het midden kan er twee kanten op geteld worden.

Merk op dat de hiervoor besproken commando's h en l en hun equivalenten niet verder gaan dan de huidige regel. Als de cursor bij voorbeeld aan het eind van de regel staat en er wordt een l gegeven, dan gaat de cursor niet naar het begin van de volgende regel. De hierna te bespreken commando's w en b doen dit wel.

Het commando w wordt gebruikt om naar het volgende woord te springen. De cursor komt dan aan het begin van het volgende woord te staan. Het commando b verplaatst de cursor naar het begin van het vorige woord. Als de cursor echter midden in of aan het eind van een woord staat, wordt naar het begin van dit woord gesprongen. Om aan het einde van een woord te komen kan e gebruikt worden. Stond de cursor al aan het einde van een woord, dan wordt naar het einde van het volgende woord gesprongen.

Om de werking van deze commando's iets te verduidelijken, moet het begrip 'woord' wat scherper gedefinieerd worden. Een 'woord' is een opeenvolging van \o"e'"\o"e'"n of meer letters, cijfers of underscores ('_') of een opeenvolging van \o"e'"\o"e'"n of meer leestekens. Merk op dat dit de definitie is zoals die voor w, b en e gehanteerd wordt. In een andere definitie kan een woord omschreven worden als de opeenvolging van \o"e'"\o"e'"n of meer tekens, anders dan spatie, tabulatie of nieuwe-regel teken. Deze definitie van een woord wordt gehanteerd door de commando's W, B en E. Verder is de werking van deze commando's identiek aan hun kleine-letter equivalenten. .lp In dit verband kunnen nog drie andere commando's genoemd worden die de cursor binnen de huidige regel verplaatsen. Het commando $ verplaatst de cursor naar het einde van de huidige regel. Om de cursor naar het eerste niet-blanko karakter te verplaatsen kan ^ gebruikt worden. Het eerste niet-blanko karakter is in veel gevallen niet het eerste karakter van een regel. Een regel kan immers beginnen met tabulaties of spaties. Om de cursor op het werkelijke begin van een regel te krijgen kan 0 gebruikt worden. In de onderstaande figuur staan al deze commando's naast elkaar:

Gebruik nu de file kalender94 die je in hoogdstuk 2 aangemaakt hebt om deze vi commando's te oefenen. Start de editor met het commando
   vi kalender94
Verlaat de editor weer nadat je alle commando's om de cursor te verplaatsen uitgeprobeerd hebt met :q.

5.3 Invoegen van tekst

Door een tekst heen wandelen is belangrijk, maar is niet de uiteindelijke bedoeling van een editor. Een editor is ontworpen om in een tekst op bepaalde plaatsen veranderingen aan te brengen. In de meeste gevallen zijn deze veranderingen toevoegingen. Immers, wanneer een nieuwe tekst gecreerd wordt is deze leeg en kan er slechts door toevoegingen een tekst ontstaan.

vi kent twee basis commando's om tekst toe te voegen: a (append) en i (insert). In feite zijn deze commando's identiek met als enige verschil dat i de tekst voor de huidige positie invoegt terwijl a de tekst na de huidige positie invoegt. Na het geven van n van deze commando's kan een willekeurige hoeveelheid tekst ingevoerd worden. Dit invoeren wordt be\o'e"'indigd zodra de ESCAPE toets aangeslagen wordt. Tijdens het invoeren is vi dus in de invoer mode waardoor alle ingetypte karakters in de tekst verschijnen in tegenstelling tot de commando mode, waarin de ingetypte karakters als commando's geïnterpreteerd worden.

Een variant van a is A. Dit is ook een append commando maar plaatst de cursor op het laatste karakter van de huidige regel alvorens met de eigenlijke append operatie te beginnen. Het A commando is dus een synoniem voor $a. Ook i kent als variant I, die analoog hieraan werkt. Het commando I heeft namelijk tot gevolg dat de cursor op de eerste niet-blanko positie van de huidige regel geplaatst wordt waarna de insert operatie gestart wordt. Met andere woorden, I is een synoniem voor ^i (twee karakters: '^' en 'i', dus niet control-I).

In veel gevallen moeten er regels toegevoegd worden, voor of achter een specifieke regel in de file. Er moet dus een opening gemaakt worden tussen twee bestaande regels. Hiervoor dienen de commando's o en O. Deze commando's hebben tot gevolg dat er een nieuwe regel geopend wordt, de cursor aan het begin van deze nieuwe regel geplaatst wordt en vi in invoer mode gaat. Er kan dus tekst ingevoerd worden die dan weer afgesloten wordt met een ESCAPE. Het commando o opent een nieuwe regel onder de huidige regel en O doet het zelfde maar dan boven de huidige regel.

Om dit te oefenen gaan we een boodschappen lijstje maken met vi. Geef het commando

% vi boodschappen
Je krijgt dan het volgende te zien:
~
~
~
~
~
~
~
~
~
~
"boodschappen" [New file]
De tildes ('~') aan het begin van iedere regel geven aan dat er nog niets in de file staat. Type nu:
uien
De letters 'u' en 'i' komen niet op het scherm; alleen de tekst "en" wordt zichtbaar. Dit komt omdat vi start in commando mode. De toetsen 'u' en 'i' worden als commando's opgevat. De 'i' is het insert commando waardoor vi over gaat naar de invoer mode. De daarop volgende tekst ("en") komt dus wel op het scherm te staan. Gebruik nu BACKSPACE om de tekst te wissen en type de volgdende regels in:
uien
boter
koek
Type nu om de file boodschappen op te slaan:
:w
In plaats van de file weg te schrijven verschijnt echter de tekst ":w" gewoon op het scherm. Je zit immers nog in invoer mode. Gebruik weer de BACKSPACE om de tekst ":w" weg te halen en geef dan ESCAPE om de invoer mode te verlaten en terug te keren naar commando mode. Als je nu :w intypt verschijnt dit onderaan het scherm. Sluit het commando af met RETURN en de file boodschappen wordt opgeslagen. Onderaan het scherm geeft vi de melding:
"boodschappen" [New file] 4 lines, 17 characters
Hieraan kun je zien dat alles goed gegaan is. Geef nu het commando :q om de editor te verlaten. Je komt dan weer terug in de shell. Controleer met ls of de file boodschappen inderdaad is aangemaakt.

Start nu weer vi om de file boodschappen te gaan wijzigen. Ga met de cursor naar de regel waar "koek" staat en ga vervolgens naar het einde van die regel. Geef nu het commando a en type de tekst "jes" in. Sluit dit af met ESCAPE om weer terug te keren naar commando mode. Het woord "koek" is nu veranderd in "koekjes". Probeer de editor te verlaten met :q. Je ziet dat vi dit weigert omdat de gemaakte veranderingen nog niet opgeslagen zijn. Met het commando :q! wordt de editor wel verlaten zonder de veranderingen op te slaan. De originele file boodschappen blijft dus behouden.

5.4 Text wijzigen

Ook moeten vaak kleine correcties aangebracht worden in een reeds bestaande tekst. Vaak bestaan dergelijke correcties uit het veranderen of verwijderen van één of slechts enkele karakters. Om een enkel karakter weg te halen kan het x of X commando gebruikt worden. Het commando x verwijdert het karakter waar de cursor op dat moment op staat; X haalt het karakter juist voor de cursor weg.

Met r (replace) wordt één karakter vervangen door één ander karakter. Het karakter wat het huidige karakter vervangt wordt direkt achter de r ingetypt. De editor komt in dit geval dus NIET in invoer mode! Het is ook mogelijk één enkel karakter te vervangen door een tekst van meerdere karakter met s (substitute). Op de plaats van het karakter waar de cursor op staat komt dan de met ESCAPE afgesloten tekst.

Een variant van r is R. Hierdoor worden meerdere karakters vervangen door de ingetypte tekst. In principe worden er evenveel karakters vervangen als er ingetypt worden. Vanzelf sprekend moet deze invoer weer afgesloten worden met ESCAPE. Het R commando is dus een methode om bestaande tekst te overschrijven. Als variant van s zou S verwacht kunnen worden maar S heeft niet de uitwerking die er in eerste instantie van verwacht zou kunnen worden. In plaats van het vervangen van een enkel karakter, vervangt S een gehele regel. In feite is S dus een synoniem voor cc (zie verderop).

Wanneer een klein aantal karakters vervangen moet worden, kan s vooraf gegaan worden door een getal. Dit getal geeft dan het aantal karakters aan wat door de ingevoerde tekst vervangen wordt. Ook met x of X kan het opgeven van een getal handig zijn. Dit getal geeft dan uiteraard aan hoeveel karakters verwijderd worden. Een getal voor r geeft het aantal (identieke) karakters wat het huidige karakter vervangt. Wordt bij voorbeeld het commando 6rp gegeven, dan wordt het karakter waar de cursor op dat moment op staat vervangen door zes p's.

Wanneer er wat uitgebreidere wijzigingen aangebracht moeten worden, zijn x, r en s niet zo handig. Om grotere stukken tekst tegelijk weg te halen of te veranderen zijn de commando's d (delete) en c (change) meer geschikt. Deze commando's zijn zogenaamde operators. Dit betekent dat ze op een object werken waardoor ze een groot scala van varianten kennen. In hun eenvoudigste vorm opereren ze op de huidige regel. De huidige regel is dan het object. Hiertoe wordt de letter van het commando simpelweg herhaald. Dus dd verwijdert de huidige regel en cc verandert de huidige regel. Uiteraard kunnen de d en c commando's vooraf gegaan worden door een getal. Dit getal geeft dan het aantal malen aan dat een operatie uitgevoerd moet worden. Om een voorbeeld te geven: 5dd haalt vijf opeen volgende regels weg.

Een object waarop een operator werkt is in feite een commando wat de cursor verplaatst. Zo wordt bij voorbeeld de cursor naar het volgende woord gebracht met w, dus dw verwijdert alle karakters tot het begin van het volgende woord. Bovendien kan w vooraf gegaan worden door een getal. Dus om drie opeen volgende woorden te verwijderen kan d3w gebruikt worden. Een heel handige variatie is cw (change word). Hierdoor wordt een woord veranderd. Ook de zoek- en sprong commando's werken als objecten. Zo wordt bij voorbeeld door d/tafelRETURN alle tekst vanaf de huidige positie tot aan de eerste keer dat het woord 'tafel' voorkomt gewist. Volgens de zelfde regels heeft d$ tot gevolg dat alles vanaf de huidige cursor positie tot aan het eind van de regel gewist wordt. In plaats van d$ kan ook de afkorting D gebruikt worden. Evenzo is voor c$ de afkorting C ter beschikking.

Het c commando plaatst een '$' aan het eind van het object dat veranderd gaat worden. Daarna wordt vi in de invoer mode geplaatst en kan de nieuwe tekst ingevoerd worden, afgesloten met een ESCAPE, zoals gebruikelijk.

Steeds wordt, wanneer er een verandering aangebracht wordt, deze automatisch door vi onthouden. Hierdoor is het mogelijk per vergissing gemaakte wijzigingen weer ongedaan te maken met u (undo). Merk op dat een tweede maal geven van het u commando de wijziging weer terug haalt. Met andere woorden, het ongedaan maken wordt weer ongedaan gemaakt. Ook kan een gemaakte verandering (of invoeging of verwijdering) herhaald worden. Het . (punt) commando herhaalt het laatste commando wat een wijziging tot gevolg had. Een voorbeeld van een toepassing is bijvoorbeeld iedere keer dat 'tafel' voor komt, dit woord te veranderen in 'stoel'. Om te beginnen wordt 'tafel' opgezocht met /tafelRETURN. De cursor komt dan aan het begin van het eerst gevonden woord 'tafel'. Met cwstoelESCAPE wordt de tafel veranderd in een stoel. Hierna kan met n (zie verderop) de volgende tafel opgezocht worden die dan met . veranderd kan worden in een stoel.

5.5 Springen en zoeken

In een file kan iedere regel gedentificeerd worden met zijn regelnummer. Zo heeft de eerste regel nummer 1, de tweede regel nummer 2, etc. Dit wordt bij voorbeeld door de meeste compilers gebruikt om de plaats aan te geven waar fouten in de tekst ontdekt worden. In vi kan dan naar een bepaalde (door zijn regel nummer aangeduide) regel toe gesprongen worden met het G (goto) commando. Het regelnummer gaat dan vooraf aan de G, bij voorbeeld met 23G wordt naar regel 23 gesprongen. Als aan G geen getal vooraf gaat wordt naar de laatste regel gesprongen.

Een andere manier om door de tekst te springen is zoeken naar een bepaald woord of combinatie van woorden. Aan vi kan een dergelijk zoek-woord opgegeven worden door middel van het / commando. Als uitzondering op de regel, moet het / commando (en ook het verderop besproken ? commando) afgesloten worden met een RETURN. Het woord waarnaar gezocht moet worden, wordt direkt na de / opgegeven. Wel moet er op gelet worden dat dit woord geen speciale tekens bevat. Er wordt namelijk niet letterlijk naar een woord gezocht, maar naar een zogenaamde 'regular expression'. De 'regular expressions' worden verderop in deze sectie besproken. Het / commando heeft tot gevolg dat er voorwaarts in de tekst gezocht wordt. Indien het einde van de file bereikt is en het te zoeken woord (expression) is nog steeds niet gevonden dan gaat vi stilzwijgend verder aan het begin van de tekst. In de andere richting zoeken is ook mogelijk, en wel met het ? commando. Ook hier wordt weer een woord (regular expression) meegegeven waarnaar gezocht moet worden. Evenals het / commando gaat het ? commando verder aan het eind van de tekst als de zoek operatie bij het bereiken van het begin nog niet geslaagd is.

Om nogmaals naar het zelfde woord te zoeken behoeft het / of ? commando niet nog een keer gegeven te worden. Simpelweg n (next) is voldoende. Er wordt dan in de zelfde richting gezocht. De zoek richting is dus afhankelijk van het feit of er het laatst een / of een ? commando is gegeven. Om in de tegengestelde richting te zoeken kan N gebruikt worden.

Om uit te vinden welke file ge-edit wordt en op welke regel de cursor zich bevindt, kan ^G gebruikt worden. vi laat dan de naam van de file zien en het feit of de file al dan niet gewijzigd is, evenals het nummer van de huidige regel, het nummer van de laatste regel en de relatieve positie binnen de file, bij voorbeeld:

 "tekst.file" [Modified] line 329 of 1276 --8%--
De plaats waar de cursor op een bepaald moment staat wordt de context genoemd. Deze context wordt door vi onthouden iedere keer wanneer er een sprong wordt uitgevoerd, bij voorbeeld door een G, /, n of N commando. Om naar een context terug te keren wordt ` ('backquote') gebruikt. Wordt deze backquote gevolgd door nog een backquote (dus: `` ) dan wordt terug gesprongen naar de vorige context. Dit is dus de context voordat de sprong uitgevoerd werd. Een context kan ook expliciet gemarkeerd worden en wel met het m (mark) commando. De m wordt altijd gevolgd door een letter; de naam van de markering. Als bij voorbeeld op een gegeven moment het commando ma gegeven wordt, wordt de huidige plaats gemarkeerd met de naam 'a'. Hierna kan de cursor op alle willekeurige manieren verplaatst worden. Om dan weer terug te keren naar de met 'a' gemarkeerde context dient het commando `a gegeven te worden.

5.6 Verplaatsen en kopieren

Een andere veel voor komende bewerking in een editor is het verplaatsen en copiëren van stukken tekst. Hiertoe heeft vi een buffer. Steeds wanneer een commando gegeven wordt waardoor tekst verwijderd of veranderd wordt, wordt de oorspronkelijke tekst in de buffer opgeslagen. Merk op dat een volgende verwijdering of verandering de inhoud van deze buffer weer overschrijft. Tekst kan in de buffer geplaatst worden door middel van het y (yank) commando. Voor het opslaan van verwijderde en ge-'yankte' tekst worden dus dezelfde buffers gebruikt.

Het y commando is een operator. Dit houdt in dat y op objecten opereert, evenals d en c. Ook de huidige regel kan als object gebruikt worden door, net als voor d en c, de y te herhalen: yy. Een handige afkorting voor yy is Y. Het verschil is dus eigenlijk dat d de tekst verwijdert terwijl y dit niet doet.

De in een buffer opgeslagen tekst kan terug gehaald worden met p (put). De inhoud van de buffer wordt dan in de tekst gecopieerd, achter de huidige positie. Met P wordt de buffer inhoud juist voor de huidige positie ingevoegd. Als de in de buffer opgeslagen tekst uit gehele regels bestaat, wordt de huidige regel niet aangetast. Er worden dus complete nieuwe regels gevormd. In die situatie werken p en P ongeveer hetzelfde als o en O.

Om een voorbeeld van de toepassing te geven: xp is een kort commando om twee karakters te verwisselen. Immers, door x wordt het karakter waar de cursor op staat verwijderd. Dit karakter komt dan in de buffer terecht. Tevens komt de cursor op het volgende karakter te staan, wat nu het huidige karakter is. De p heeft tot gevolg dat het karakter uit de buffer achter het (nieuwe) huidige karakter geplaatst wordt. De karakters zijn dus van plaats gewisseld. Een tweede voorbeeld is YP. Deze sequentie van commando's maakt een copie van de huidige regel en plaatst deze copie juist boven die huidige regel.

5.7 Regular expressions

Een regular expression in zijn eenvoudigste vorm is een simpel woord. Met speciale karakters, zogenaamde meta-karakters kunnen ingewikkelde constructies gebouwd worden om de meest uiteen lopende uitdrukkingen te vinden. Een regular expression wordt gebruikt om in een tekst naar bepaalde uitdrukkingen te zoeken. Het concept van regular expressions wordt in UNIX veel toegepast, niet alleen in vi en ex, maar ook in onder andere grep en lex. Als een regular expression in een uitdrukking past wordt gezegd dat de regular expression matcht. Als bijvoorbeeld als regular expression het woord "weerstand" opgegeven wordt, onstaat er een match als ook in de tekst een woord staat wat "weerstand" omvat. Voorbeelden van een match in dit geval zijn "weerstandswaarde" maar ook "luchtweerstand" en "weerstand" zelf.

In feite matcht iedere regular expression slechts één karakter. Een string van meerdere karakters wordt dus gematchd door regular expressions achter elkaar te zetten. De eenvoudigste regular expression is dus het karakter wat gematchd moet worden. Bij voorbeeld de regular expression p match iedere "p". Worden twee van deze expressies achter elkaar geplaatst, bijvoorbeeld pi dan wordt ieder woord waar "pi" in zit gematchd. Op deze manier kunnen dus alle woorden letterlijk gevormd worden. Daarnaast kunnen de meta-karakters gebruikt worden. De meta-karakters voor de normale regular expressions in vi en ex zijn '^' aan het begin van een expressie, '$' aan het eind van een expressie, '*' indien dit niet het eerste karakter is, '.', '\', '[' en '~'. Aangezien de meta-karakters een speciale betekenis hebben zouden zij zelf niet in de tekst opgezocht kunnen worden. Om dit toch mogelijk te maken dienen zij ge-'escaped' te worden met een backslash ('\'). De regular expression "\$" matcht dus een "$" in de tekst.

Als een regular expression vooraf gegaan wordt door een '^', wordt alleen een match gevonden aan het begin van een regel. Dus: ^Data vindt alleen een match als het woord "Data" aan het begin van een regel staat. Bovendien heeft '^' nog een andere speciale betekenis als deze aan het begin van een string tussen vierkante haakjes (brackets, '[]') staat; zie verderop. Een regular expression kan ook gematcht worden aan het eind van een regel. Dit vindt plaats wanneer de regular expression gevolgd wordt door een '$'. Een combinatie van deze meta-karakters is ook mogelijk. Bij voorbeeld ^database$ matcht het woord "database" als dit het enige woord op de hele regel is (er mogen dus ook geen spaties voor of achter staan). Een ander voorbeeld: met ^$ worden alleen lege regels gevonden.

Het is ook mogelijk een verzameling karakters te matchen. De eenvoudigste expressie hiervoor is het meta-karakter '.' (punt). Door de punt wordt ieder karakter gematchd, behalve het nieuwe-regel teken. Om bij voorbeeld te zoeken naar zowel "lezen" als "leven" kan de regular expression le.en gebruikt worden. Ook de woorden "leren" en "leden" worden hierdoor gematcht. De verzameling karakters kan verder beperkt worden door een character class op te geven. De karakters die gematchd moeten worden komen dan tussen vierkante haakjes ('[]') te staan. Om bij voorbeeld alleen op "lezen" en "leven" te matchen kan de regular expression le[vz]en gebruikt worden. In een character class zijn '^' en '-' meta-karakters. Het min-teken ('-') wordt gebruikt om een verzameling aan te geven van karakters die tussen twee karakters in liggen. Zo kan de bovenstaande regular expression ook geschreven worden als le[v-z]en. Hierdoor worden dan wel de 'tussen liggende' woorden "lewen", "lexen" en "leyen" ook gematcht. Merk op dat een character class precies één karakter matcht. Dus [abc] matcht een "a", een "b", of een "c" en niet de opeenvolging "abc". Door de regular expression [a-z] worden alle kleine letters gevonden. Wanneer een character class begint met een '^', betekent dit dat alle karakters die niet binnen de opgegeven verzameling vallen gematchd worden. Dus: [^a-z] matcht alle karakters behalve de kleine letters en uiteraard het nieuwe-regel teken.

Zoals reeds vermeld, kan het matchen van een regular expression beperkt worden tot het begin of einde van een regel door middel van ^ en $. Het is ook mogelijk de matching te beperken tot het begin of einde van een woord. Een woord wordt in dit geval gedefinieerd als de opeenvolging van één of meer karakters uit de verzameling [a-zA-Z0-9_]. Wordt een regular expression vooraf gegaan door de combinatie \< dan wordt deze regular expression alleen gematched aan het begin van een woord. Dat wil zeggen, aan het begin van een regel of juist voor een letter, cijfer of underscore en na een karakter wat geen letter, cijfer of underscore is. Zo wordt met \<test wel "test" gevonden, maar niet "beeldtest". Ook kan het matchen beperkt worden op het einde van een woord of het einde van een regel, door achter de regular expression de combinatie \> te plaatsen. Bij voorbeeld: om wel "start" te vinden, maar niet "starten" kan de expressie start\> gebruikt worden.

Ook de herhaling van een expressie kan gematchd worden. Met het meta-karakter '*', namelijk worden nul of meer herhalingen van de voorafgaande regular expression gevonden. Met de regular expression bo*t wordt zowel "bot" als "boot" gevonden, maar ook "bt", "booot", "boooot", etc.

5.8 Meer text objecten

Het concept van de tekst objecten is hierboven reeds aan de orde gekomen. De mogelijkheden van vi zijn hiermee echter nog lang niet uitgeput. Het is bij voorbeeld ook mogelijk de cursor te verplaatsen naar een specifiek karakter. Hiertoe dient het f (find) commando. Dit commando wordt gevolgd door een karakter. Vi gaat dan op de huidige regel vanaf de cursor positie zoeken naar de eerste keer dat dit karakter voor komt. De cursor komt dan op het gevonden karakter te staan. Wordt in plaats van f een t (to) commando gebruikt, dan komt de cursor juist voor het gevonden karakter terecht. Zoeken f en t vooruit, met F en T worden de zelfde zoekacties uitgevoerd, maar dan achteruit. Merk op dat T de cursor achter het gevonden karakter plaatst. Elk van de commando's t, T, f en F kan door middel van een enkele toets herhaald worden met het ; commando. Met het commando , (komma) wordt de zoekaktie herhaald in tegengestelde richting (vergelijk n en N ). Verder kan de cursor worden verplaatst naar een specifieke kolom binnen de huidige regel met |. de kolom wordt aangegeven door het getal wat aan | vooraf gaat, bij voorbeeld 40| zet de cursor in de huidige regel op het veertigste karakter.

Soms is het handig een document op te delen in zinnen, alinea's en secties (sentences, paragraphs and sections). Deze tekst objecten worden ook door vi onderkend. Onder een zin verstaat vi alles wat afgesloten is met een '.', '!' of '?', gevolgd door een nieuwe regel teken of twee spaties. Eventueel mogen hier tussen nog een willekeurig aantal sluit-haakjes ')' en ']', en aanhalingstekens (' en ") staan. De commando's ( en ) verplaatsen de cursor respectievelijk naar het begin van de voorgaande en volgende zin.

De cursor wordt over alinea's bewogen met { en }. Een alinea begint hierbij altijd met een lege regel of met macro's die een nieuwe alinea aanduiden in de -mm en -ms pakketten van nroff. Analoog hieraan kan de cursor over secties bewogen worden met [[ en ]]. Ook hier worden weer nroff macro's gebruikt om het begin van een nieuwe sectie te vinden. Verder onderscheidt vi secties door een formfeed (^L) in de eerste kolom van een regel.

Met name voor programmeurs spelen haakjes en accolades een belangrijke rol. Deze tekens komen steeds in paren voor. In gecompliceerde expressies is het steeds een moeilijk karwei de bij elkaar behorende haakjes te vinden om zo de juistheid van een expressie te controleren. Met % zijn paren van haakjes snel gevonden. Bevindt de cursor zich op een haakje ('(', '{', ')' of '}'), dan kan de cursor door middel van % naar het bij behorende haakje openen danwel sluiten verplaatst worden.

5.9 Ex commando's

vi is een 'full screen' editor die geheel gebaseerd is op de 'line' editor ex. ex is dan ook als onderdeel in vi aanwezig. Dit heeft tot gevolg dat alle commando's van ex in vi te bereiken zijn. Om een ex commando aan te roepen wordt : gebruikt. Enkele van deze commando's zijn aan het begin van dit hoofdstuk reeds besproken: :q, :q!, :w, :wq en :x. Als gemeenschappelijke eigenschap worden deze commando's steeds afgesloten met ESCAPE of RETURN. Wordt een commando afgesloten met RETURN dan wordt commando uitgevoerd. Een commando wat afgesloten wordt met ESCAPE wordt geaborteerd.

De belangrijkste ex commando's zijn file manipulatie commando's. Het commando :w is reeds besproken. Dit commando is echter een eenvoudige versie van de algemene vorm x,yw naam. Dit commando schrijft de regels vanaf regel x tot en met regel y naar de file met de naam naam. De regelnummers kunnen hierbij eventueel weg gelaten worden. Wanneer de file reeds bestaat weigert vi om deze te overschrijven. In dat geval kan :w! in plaats van :w gebruikt worden om de file toch te overschrijven. Het lezen van een externe file is ook mogelijk, en wel met het :r (read) commando. Het commando :r naam leest de file naam in de huidige tekst in. Deze externe tekst behoeft echter niet altijd uit een echte file te komen. Ook de uitvoer van een commando kan direkt in de tekst opgevangen worden. Zo leest bij voorbeeld :r !ls -l de uitvoer van ls -l en plaatst dit direkt in de tekst.

Het :e commando staat voor 'edit'. Als hierbij de naam van een file opgegeven wordt, kan deze file ge-edit worden. Het uitroep teken heeft ook hier weer de betekenis "Trek je van gemaakte veranderingen niets aan". Het commando :e! heeft dus tot gevolg dat alle veranderingen in de huidige file genegeerd worden en de file opnieuw ingelezen wordt. Ook kan de te editen file veranderd worden met "edit next file", :n. Dit gaat uiteraard alleen op als aan vi meer dan één file is opgegeven, bij voorbeeld op de commando regel die vi startte. Als alternatief, kan vi achteraf een lijst van files gegeven worden, met :n file....

Zoals ieder zichzelf respecterend interaktief programma, kent vi ook een shell escape. Dit geeft de mogelijkheid om vanuit vi een willekeurig programma op te starten. In feite wordt er een shell gestart waaraan het commando doorgegeven wordt. Het commando hiervoor is :!command. Zodra het commando uitgevoerd is vraagt vi om de RETURN toets aan te slaan. Als dat gebeurd is maakt vi het scherm schoon en schrijft de tekst opnieuw.

Behalve file manipulatie en de shell escape zijn er natuurlijk ook de 'normale' edit commando's van ex. Het :i commando voert alle ingevoerde tekst in boven de huidige regel. Dit invoeren stopt wanneer er een regel wordt ingevoerd die alleen één punt bevat. Bijna alle ex commando's kunnen vooraf gegaan worden door één of meer regelnummers ofwel adressen. In deze adressen hebben sommige karakters een speciale betekenis. Zo staat bij voorbeeld '.' voor de huidige regel en '$' voor de laatste regel. Dus :20i voegt regels in, boven regel 20. Het zou echter te ver voeren alle ex commando's uitvoering te bespreken. Hiervoor wordt verwezen naar de handleidingen. Bovendien zijn voor vrijwel alle commando's equivalenten in vi beschikbaar. Eén commando uit ex is nog wel een vernoeming waard omdat het ontzettend krachtig is. Dit is het global commando :g. Hiermee is door de gehele tekst heen een verandering aan te brengen. De algemene vorm van het global commando is :x,yg/pat/cmds. De adressen (regelnummers) mogen hierbij weg gelaten worden. Daar wordt dan "1,$" voor ingevuld met als resultaat dat de gehele file bewerkt wordt. Het argument pat is een regular expression die aangeeft welke regels binnen het opgegeven bereik geselecteerd worden. Op die regels worden dan de (ex-) commando's los gelaten die in cmds gespecificeerd zijn. Zo wordt bijvoorbeeld met het commando :4,30g/jaar:/s/89/90/ in iedere regel tussen regel 4 en regel 30 waarin "jaar:" voor komt de eerst voorkomende "89" veranderd in "90". Merk op dat het eigenlijke veranderen veroorzaakt wordt door het 'substitute' commando s/89/90/.

6 Netwerken

Het klassieke beeld van de computer is een grote machine in een aparte kamer waar de gebruikers hun rekenwerk naar toe komen brengen. De laatste deciennia is echter steeds meer een trend zichtbaar waarin die ene grote computer vervangen wordt door een groot aantal kleine (personal) computers. Iedere gebruiker heeft heeft zijn eigen programma's en gegevens. Wel moeten die gebruikers dan hun gegevens met elkaar kunnen uitwisselen. Sterker nog, wanneer verschillende mensen op verschillende machines aan het zelfde project werken, kunnen de gegevens op slechts één computer opgeslagen worden. Zouden namelijk de zelfde gegevens op verschillende machines opgeslagen zijn dan weet op den duur niemand meer welke de juiste zijn. Worden die (kleine) machines in een netwerk aan elkaar gekoppeld, dan kunnen deze problemen bij voorbaat geëlimineerd worden.

Dit is slechts één van de mogelijke toepassingen van een netwerk. Een andere toepassing behelst het verbeteren van de performance, en wel volgens het 'verdeel en heers' principe. Door de werklast te verdelen over een aantal kleine computers kan een grotere performance behaald worden dan wanneer één grote mainframe al het werk zou moeten doen. Tevens wordt hiermee een hogere betrouwbaarheid behaald. Als één van de processors in een goed ontworpen netwerk uit valt zal de performance voor alle gebruikers iets dalen. Dit is aanzienlijk gunstiger dan het in de kou laten staan van enkele gebruikers. Niet alleen proocessors maar ook andere hulpbronnen zoals disks, printers, programma's en databases kunnen aan alle gebruikers in een netwerk ter beschikking gesteld worden. Een dergelijke hulpbron behoeft dan niet op iedere machine aanwezig te zijn. Deze aanpak leidt tot het koppelen van een groot aantal machines die dicht bij elkaar staan, waardoor een lokaal netwerk of Local Area Network (LAN) ontstaat. Dit in tegenstelling tot een long haul netwerk wat meestal is opgebouwd met machines die enkele tot vele honderden kilometers van elkaar vandaan geplaatst zijn.

6.1 Het lokale netwerk

De meeste leveranciers bieden de mogeljkheid computers en workstations in een Ethernet met elkaar te verbinden. Dit is een soort netwerk waarin alle machines op één enkele kabel zijn aangesloten en iedere machine met iedere andere machine gegevens kan uitwisselen. Iedere computer die op het netwerk is aangeloten heeft zijn eigen naam, de hostname. Om er achter te komen wat de naam van de computer is waar je op werkt, gebruik je het commando hostname. De naam van de computer verschijnt dan op het scherm, bij voorbeeld:

% hostname
sphinx
%
De namen van alle machines die in het netwerk aanwezig zijn staan in de file /etc/hosts Om die te lezen geef je bij voorbeeld het commando:
% cat /etc/hosts
#
# Internet host table
#
127.1           localhost loghost loopback me
192.1.2.1       sphinx.voorbeeld        sphinx
192.1.2.2       obelisk.voorbeeld       obelisk
192.1.2.3       pyramid.voorbeeld       pyramid
%
Als de Yellow Pages (of NIS) op het systeem geinstalleerd zijn zul je met ypcat hosts de namen van de op het netwerk aangesloten machines moeten lezen. Je ziet in deze file op iedere regel het (Internet) adres van de machine, de officiële, volledige naam en mogelijk een aantal bijnamen van de machine. In het voorbeeld hierboven zijn de namen verzonnen. Kijk in de /etc/hosts file welke machines er werkelijk aangesloten zijn.

Een netwerk geeft de gebruikers van die machines ongekende mogelijkheden om de faciliteiten op andere machines te benutten. Zo is het bij voorbeeld mogelijk om via het lokale Ethernet op een andere machine in te loggen met rlogin (remote login). Stel, je bent ingelogd op de machine 'sphinx'. Log dan in op de machine 'obelisk' met het commando:

% rlogin obelisk
Password:
UNIX System V Release 4.0 AT&T Amiga (Unlimited)
obelisk
Copyright (c) 1984, 1986, 1987, 1988 AT&T
All Rights Reserved
Last login: Mon Feb 14 13:16:29 from localhost
        System V Release 4.0            Amiga Version 2.1p2a
%
Je logt dan in op 'obelisk' met dezelfde userid als waarmee je op 'sphinx' was ingelogd. In sommige situaties zal ook hier voor het inloggen om een password gevraagd worden. Vaak is dat niet wenselijk aangezien dezelfde persoon op verschillende machines een userid kan hebben. Om te voorkomen dat er voor remote login een password nodig is, kun je een file .rhosts in je HOME directory aanmaken met daarin de namen van alle machines waarvandaan je zonder password kunt inloggen. Deze .rhosts file zou er bij voorbeeld als volgt uit kunnen zien:
sphinx.voorbeeld
obelisk.voorbeeld
Op iedere regel staat de volledige naam van een machine waarvandaan je met dezelfde userid remote kunt inloggen zonder dat hier een password voor nodig is. Let er wel op dat de volledige naam van de machine hier genoemd moet worden. Bijnamen zijn hier dus niet bruikbaar. In het bovenstaande voorbeeld kun je dus vanaf 'sphinx' en 'obelisk' zonder meer inloggen. Zou je vanaf 'pyramid' inloggen, dan moet je alsnog een password geven. Op veel systemen die in een netwerk zijn opgenomen is een 'globale' .rhosts file aanwezig die voor alle gebruikers geldt. Dit is de file /etc/hosts.equiv. Als een hostname daar al in vermeld staat is het niet nodig om deze ook nog eens in je eigen .rhosts file te zetten.

Je bent nu via het netwerk vanaf 'sphinx' ingelogd op 'obelisk'. Je kunt verder door het netwerk reizen naar 'pyramid' met het commando

% rlogin pyramid
Natuurlijk kun je vanaf pyramid weer doorgaan (dus niet terug) naar de plaats waar je begonnen was:
% rlogin sphinx
Je hebt nu een rondje gemaakt door het netwerk, zoals de onderstaande figuur weergeeft:

Op deze manier kun je remote in blijven loggen tot je op een gegeven moment niet meer weet waar je zit of hoe vaak je een bepaalde machine gepasseerd bent. Om weer in de uitgangssituatie terug te komen moet je langs de omgekeerde weg weer uitloggen:

% exit
Connection closed.
Je bent nu weer terug op 'pyramid'.
% exit
Connection closed.
Nu ben je terug op 'obelisk'.
% exit
Connection closed.
En nu pas ben je weer terug op 'sphinx', waar het hele verhaal begonnen is. Houdt er dus rekening mee dat je net zo vaak moet uitloggen als je remote inlogt.

Je kunt rlogin niet in alle situaties gebruiken om op andere machines in het netwerk in te loggen. rlogin is alleen bruikbaar om via het Ethernet op een andere UNIX machine in te loggen. Wanneer je wilt inloggen op een machine waarop geen UNIX draait maar die wel in het Ethernet is opgenomen (een PC of Amiga), kan telnet gebruikt worden. Hiermee wordt een direkte (terminal) verbinding opgebouwd met een willekeurige machine in het Ethernet. telnet is een interaktief programma wat een eigen set commando's kent. Met het commando ? (vraagteken) krijg je een overzicht van de beschikbare commando's.

Ook inloggen op machines buiten het Ethernet is mogelijk. Er wordt dan veelal gebruik gemaakt van RS232 verbindingen, eventueel via de telefoon. Wanneer een verbinding met het telefoon net opgebouwd wordt, moet er uiteraard wel een modem aan beide zijden aanwezig zijn. Een van de commando's waarmee zo'n verbinding tot stand gebracht kan worden is cu (Call Unix). Als alternatief voor een dergelijke communicatie kan kermit of minicom gebruikt worden.

Files en directories kunnen van de ene machine naar de andere getransporteerd worden met rcp (Remote CoPy). Om de file kalender94 te kopiëren naar de file jaarkalender op de machine 'obelisk' geef je het commando:

% rcp kalender94 obelisk:jaarkalender
%
De filenaam op de andere (remote) machine wordt dus voorafgegaan door de naam van de machine, gevolgd door een dubbele punt. De vorm van rcp is dus gelijk aan die van cp met dit verschil dat iedere filenaam de vorm:
    hostname:pathname
kan hebben. Wordt de hostname met de dubbele punt weggelaten of begint de naam met een '/', dan wordt daar een lokale file mee bedoeld. Is de pathname een relatieve pathname (begint niet met een '/'), dan wordt de naam geïnterpreteerd ten opzichte van de HOME directory op hostname.

Uiteraard moet rcp wel in kunnen loggen op de andere machine, en wel zonder daar een password voor te geven. Kan rcp niet zonder meer inloggen, dan wordt niet om een password gevraagd, maar geeft rcp alleen de foutmelding:

Permission denied.
Denk er dus aan om de machine namen waar vandaan je files wilt transporteren in de .rhosts file in je HOME directory te zetten.

Is telnet de tegenhanger van rlogin, ftp (File Transfer Program) is de tegenhanger van rcp. Zo kan rcp in de regel alleen tussen UNIX machines gebruikt worden, terwijl ftp files tussen willekeurige machines binnen het Ethernet kan transporteren. Bovendien kun je ftp gebruiken om files van en naar machines te transporteren waarop je niet zonder password kunt inloggen, aangezien je met ftp expliciet op de remote machine moet inloggen.

Om een commando op een andere machine uit te voeren kan rsh (Remote SHell) gebruikt worden. De algemene vorm van rsh is:

   rsh hostname command
Lees bij voobeeld de inhoud van de root directory op de machine 'obelisk' met het commando:
% rsh obelisk ls /
bin
dev
etc
home
lost+found
mnt
opt
proc
sbin
stand
tmp
unix
usr
var
%
Dit is natuurlijk niet een van de meest nuttige toepassingen van rsh. Een wat meer interessante mogelijkheid doet zich voor als je een zware rekenklus voor de computer hebt, bij voorbeeld het simuleren van een grote elektrische schakeling of het renderen van een animatie die uit enkele honderden frames bestaat. Met behulp van rsh kun je dan het werk over een aantal machines in het netwerk verdelen, waardoor het geheel veel sneller gebeurt.

Een andere toepassing van rsh is het gebruik van speciale apparatuur of software die op slechts één of hooguit een paar machines beschikbaar is. Als er bij voorbeeld op slechts één computer in het netwerk een tape streamer ingebouwd is, dan kun je toch een backup maken door met rsh de tape op die machine aan te spreken. Dit kun je bij voorbeeld doen met het commando:

% tar cf - . | rsh host_with_tape dd of=/dev/tape obs=20b
Hierin zorgt het commando
   tar cf - .
er voor dat er een backup gemaakt wordt van de huidige directory. De backup wordt naar de standaard uitvoer gestuurd. Door middel van het pipe ('|') symbool wordt de standaard uitvoer van tar naar de standaard invoer van rsh geredigeerd.

6.2 Network File System

De hierboven beschreven programma's om files te transporteren zijn min of meer overbodig wanneer gebruik gemaakt wordt van het Network File System (NFS). Het NFS is een faciliteit waarmee files door verschillende machines gebruikt kunnen worden. Het is hierbij niet noodzakelijk dat de machines identiek zijn of zelfs het zelfde operating system draaien. De files worden voor de verschillende machines toegankelijk gemaakt doordat file systems op een andere machine in de directory boom geplaatst kunnen worden. In het NFS is er steeds één machine, de server die de schijf bevat en deze geheel of gedeeltelijk aan de andere machines in het netwerk, de clients ter beschikking stelt. Hierdoor kunnen gebruikers van een client direkt over de files op de server beschikken alsof deze files lokaal op de client aanwezig zijn. Niet alleen file systems, maar ook andere diensten als printers, tapestreamers en supercomputers kunnen op deze manier op het lokale netwerk ter beschikking gesteld worden.

Als voorbeeld van het gebruik van NFS, beschouw de volgende situatie: in een netwerk is een machine, genaamd 'sphinx' en een machine, genaamd 'obelisk' met een lokale harddisk opgenomen. Een gebruiker op 'sphinx' heeft behoefte om de manual pages te lezen maar heeft deze niet in zijn eigen file system ter beschikking. Op obelisk staan de manual pages onder de directory /usr1/man. De systeem beheerder kan dan met NFS de directory /usr1/man op 'obelisk' aan een directory /usr/man op 'sphinx' hangen.

Hierna kan op 'sphinx' het man commando gebruikt worden alsof de manual pages op een lokaal file system aanwezig zijn. NFS geeft grote voordelen met betrekking tot het beheren van file systems. Niet alleen voor de systeem beheerder maar ook voor de gebruikers zelf. Zo zullen in veel situaties de home directories van alle gebruikers via NFS toegangkelijk zijn. De werkelijke files staan dan op één centrale machine opgeslagen en alle andere machines spreken via het netwerk dezelfde fysieke schijf aan. Het maakt dan niet uit op welke machine je inlogt, je krijgt altijd dezelfde directory voorgeschoteld. Dit geeft niet alleen een enorme besparing op de totale hoeveelheid opslagruimte, het voorkomt ook dat op verschillende machines verschillende versies van dezelfde files rondslingeren.

6.3 Oefeningen

  1. Transporteer een file uit je home directory naar een computer waarvandaan je de file op een floppy mee naar huis kunt nemen.
  2. Doe ook het omgekeerde. Dat wil zeggen, transporteer een file van een floppy naar je home directory.
  3. Bestudeer de manual page van tar.
  4. Maak een backup van je home directory naar een tape en lees deze backup ook weer terug.
  5. Kijk met behulp van df welke directories via NFS toegankelijk zijn en op welke machines die directories fysiek aanwezig zijn. Log ook (remote) in op andere machines in het netwerk om de via NFS toegankelijke directories op te zoeken.

7 Communicatie met gebruikers

UNIX is een multi-tasking, multi-user operating system. Dat wil zeggen dat er meerdere processen of taken tegelijk kunnen draaien en dat er meerdere gebruikers tegelijkertijd van de machine gebruik kunnen maken. Alvorens de machine te kunnen gebruiken moet een gebruiker eerst inloggen. Het systeem houdt dus bij welke gebruikers er ingelogd zijn. Dit geeft de mogelijkheid om met iedere andere gebruiker die op een bepaald moment ingelogd is direkt te communiceren.

7.1 Direkte communicatie

Om met ingelogde gebruikers te kunnen communiceren zul je eerst moeten weten welke gebruikers ingelogd zijn. Dit zijn is te zien met who. Hier is een voorbeeld:

% who
root       term/con2    Jan  5 13:54
arjen      pts/0        Jan 20 09:56
arjen      pts/1        Jan 20 09:56
andromed   term/con8    Jan  5 14:43
piet       term/con9    Jan  6 10:13
arjen      pts/3        Jan 27 14:12
%
Bovendien laat who zien aan welke terminal een gebruiker zit en op welk tijdstip die gebruiker is ingelogd.

Het commando

% who am i
arjen      pts/3        Jan 27 14:12
%
(dus drie woorden !) laat je eigen userid, terminal naam en het tijdstip van inloggen zien. Merk op dat who de namen geeft waaronder ingelogd is. Ook who am i doet dit. Deze naam behoeft echter niet de werkelijke naam te zijn waaronder een gebruiker op dat moment in het systeem aanwezig is. Met su (Substitute User) kan de effectieve identiteit van een gebruiker, de 'effective userid', veranderen. Deze 'effective userid' is de identiteit die werkelijk van belang is voor het controleren van permissies. Een ander commando namelijk whoami (aan elkaar vast geschreven dus) laat de 'effective userid' zien welke op dat moment geldt.

Nu je weet wie er ingelogd zijn, kun je een andere gebruiker een boodschap sturen. Type bij voorbeeld het commando:

% write piet
Hier komt de mededeling....
Alles wat je nu intypt komt op het scherm van 'piet' terecht. Om dit te beëindigen en weer terug te keren naar de shell type je een ^D (control-D). De gebruiker 'piet' krijgt dan het volgdende te zien:
        Message from arjen on ecl021 (pts/3) [ Tue Feb 15 11:25:09 ] ...
Hier komt de mededeling....
<EOT>
Zou 'piet' op meer dan één terminal ingelogd zijn, dan kun je een keuze maken uit de terminal waarnaar je de boodschap stuurt. Zonder die keuze stuurt write de boodschap naar de eerste terminal waar piet is ingelogd. Daarnaast krijg je een lijst met de andere terminals te zien:
% write piet
piet is logged on more than one place.
You are connected to "pts/0".
Other locations are:
pts/1
term/con9
pts/2
pts/3
Je kunt dan naar een specifieke terminal schrijven met:
% write piet pts/2
om via terminal pts/2 een boodschap naar 'piet' te sturen.

Uiteraard kunnen andere gebruikers op dezelfde manier boodschappen naar jou sturen. Je kunt dit blokkeren met het mesg commando:

% mesg no
%
Dit geldt dan alleen voor die bepaalde terminal (of window) waarop je het mesg commando geeft. Op andere terminals kunnen dan nog steeds boodschappen verschijnen.

write werkt prima als je een mededeling wilt versturen maar niet direkt op antwoord zit te wachten. Om interaktief met elkaar te converseren is talk beter geschikt. Geef bij voorbeeld het commando:

% talk piet
Het scherm wordt dan in twee\o'e"'n gedeeld en bovenin verschijnt de melding dat er gewacht wordt tot de tegenpartij antwoord geeft:
[Waiting for your party to respond]







------------------------------------------------------------------------------






Aan de andere kant, dus bij 'piet' verschijnt de boodschap

Message from Talk_Daemon@ecl021 at 8:52 ...
talk: connection requested by arjen@localhost.
talk: respond with:  talk arjen@localhost
Als 'piet' nu antwoordt met talk arjen@localhost wordt ook zijn scherm in twee stukken verdeeld en kan de communicatie beginnen. Alles wat je intypt verschijnt nu in het bovenste deel van het scherm en tegelijkertijd in het onderste deel van het scherm van 'piet'. Andersom gebeurt dit natuurlijk ook. Alles wat 'piet' intypt verschijnt direkt onderin jouw scherm. Je kunt de conversatie beëndigen met ^C (control-C).

7.2 Electronic mail en Usenet

Direkt communiceren met een andere gebruiker is alleen mogelijk als die gebruiker ingelogd is en niet te ver weg is (tenminste op het lokale netwerk). Is de afstand wat groter of is de tegenpartij op dat moment niet ingelogd, dan kun je talk of write niet gebruiken. Afgezien daarvan kan het nogal storend werken als je plotseling een mededeling van iemand anders op je scherm krijgt. Als derde nadeel komt de mededeling alleen op het scherm terecht. De ontvanger van de boodschap kan deze niet in een file bewaren. Een betere manier om te communiceren is daarom met behulp van elektronische post (electronic mail).

Je kunt op ieder gewenst moment mail verzenden naar andere gebruikers. Degene die de mail ontvangt wordt niet in zijn bezigheden gestoord. Sterker nog, hij of zij hoeft niet eens ingelogd te zijn. De mail blijft in een soort postbus liggen totdat het bericht gelezen wordt. Om mail te verzenden gebruik je het commando

% mail naam
%
waarin naam de userid van de geadresseerde is. Stuur een bericht naar jezelf met het commando:
% mail userid
Vul voor userid je eigen login-naam in. Je kunt nu de boodschap intypen. Let op: mail geeft geen prompt. Beëindig de boodschap met een regel waarop alleen een punt ('.') staat. Hier is een voorbeeld:
% mail arjen

Hier is een test berichtje naar mijzelf

.
%
Lees vervolgens de post die je net aan jezelf gestuurd hebt. Geef hiervoor het commando mail, dus zonder de naam van een geadresseerde er achter:
% mail
From arjen Wed Feb 16 09:48 MET 1994
From: arjen@ecl021.artmediatech.nl (Arjen Baart)
To: arjen
Date: Wed, 16 Feb 1994 09:48 MET
Content-Length: 41

Hier is een test berichtje naar mijzelf


?
Je ziet dan bovenaan wat informatie die door mail wordt toegevoegd. Onder andere de afzender en de datum van verzending. Daarna volgt het bericht zelf en de prompt van mail, een vraagteken. Hiermee wordt aangegeven dat je een commando aan mail kunt geven. Met deze commando's kun je boodschappen in een file saven, boodschappen verwijderen, een vorige boodschap laten zien, etc. Het vraagteken ('?') commando geeft een overzicht van alle commando's die mail kent. Geef je alleen een RETURN, dan komt de volgende boodschap tevoorschijn of keer je terug naar de shell als er geen boodschappen meer zijn.

In plaats van een bericht wat je intypt, kun je ook een file naar een andere gebruiker zenden. Je moet dan de invoer van mail uit een file halen met het commando:

% mail geadresseerde <filenaam
%
Van deze mogelijkheid kun je bij voorbeeld gebruik maken als je een programma of tekst aan een collega wilt overdragen.

Met mail kun je niet alleen berichten sturen naar andere gebruikers in het lokale netwerk. Je kunt in principe mail verzenden over de gehele wereld. De enige voorwaarde is dat het systeem waarop je werkt en natuurlijk ook het systeem van de geadresseerde aangesloten is op een netwerk zoals het Internet. De eenvoudigste manier om een willekeurige gebruiker een bericht te sturen is door gebruik te maken van het internet adres van die gebruiker. Dit heeft de vorm:

username@hostname.sub-domain.sub-domain.domain
Hierin kunnen net zoveel sub-domains staan als nodig is om het adres aan te geven. Om het voorbeeld van het bovenstaande bericht aan te halen, het adres:
   arjen@kithira.andromeda.nl
is het adres van de gebruiker genaamd arjen op de machine met de naam kithira Deze machine is bereikbaar in het domain andromeda wat weer een sub-domain is van het grotere domain nl. De meeste machines in Nederland vallen in het domain nl. Van rechts vandaan lezend geeft het domain dus steeds een kleiner gebied aan. Zo staat het domain ".edu" voor alle educatieve instellingen in de USA en het domain ".cs", voor Tsjecho-Slowakije.

Een andere dienst van het internet is news Met behulp van news kunt je deelnemen aan openbare discussies over de meest uiteenlopende onderwerpen, waaronder alle aspecten van computergebruik, hardware, software, tips en oplossingen voor problemen, communicatie, etc. Maar ook bijvoorbeeld op het gebied van wetenschap, kunst, recreatie en politiek. Gebruikers over de gehele wereld leveren dagelijks bijdragen in een of meerdere van de ruim 1500 verschillende nieuwsgroepen. Binnen enkele dagen, vaak enkele uren, kunnen tienduizenden andere computergebruikers deze bijdragen lezen, vragen beantwoorden en/of hun eigen ervaringen bijdragen. Naast de wereldwijde groepen bestaat er ook een aantal specifiek Nederlandse en Europese nieuwsgroepen. Ook een deel van de inhoud van het LISTSERV systeem van BITNET/EARN is binnen NLnet news beschikbaar. Alle news artikelen worden op uw lokale computersysteem opgeslagen, en kunnen door lokale gebruikers onmiddellijk gelezen worden zonder extra datatransmissiekosten. Per dag worden er meer dan 15000 news artikelen met een totale omvang van ruim 30 Mb doorgegeven.

8 De Shells

Op het eerste gezicht lijkt het heel vanzelf sprekend dat wanneer een commando getypt wordt, dit commando ook wordt uitgevoerd. Er is echter behoorlijk wat programmatuur voor nodig om de ingetypte regel te interpreteren en eventueel andere programma's aan te roepen. Om te beginnen moet een regel die vanaf een toetsenbord ingetypt wordt opgevangen worden. Dan moet uitgezocht worden welk commando bedoeld werd om vervolgens het bijbehorende programma op te zoeken en, wanneer gevonden, aan te roepen. Is een commando al dan niet succesvol afgerond, dan moet het systeem weer klaar staan om een nieuw commando uit te gaan voeren. Een programma wat deze handelingen verricht wordt een 'command interpreter' of shell genoemd. Zo'n shell wordt automatisch gestart wanneer een gebruiker inlogt omdat deze in de password file is gespecificeerd.

Een shell behoeft in principe niet gecompliceerd te zijn. Een eenvoudige shell zal een regel van zijn invoer lezen, het eerste woord van die regel als commando opvatten en een programma opzoeken wat de zelfde naam draagt om tenslotte dit programma te starten. Na beëindiging van dat programma staat de shell weer klaar voor een volgende regel. Voor de meeste toepassingen is dit echter niet voldoende. Veel programma's accepteren extra gegevens in de vorm van argumenten. Deze argumenten worden dan op dezelfde regel achter het commando ingetypt. De shell zal dan de argumenten van het commando splitsen en ze aan het aangeroepen programma doorgeven. Dit programma zal de argumenten dan verder interpreteren.

Behalve het afsplitsen van argumenten kan een shell nog meer taken verrichten, zoals het verzorgen van invoer en uitvoer, zoeken in een directory, geavanceerde substituties op het commando uitvoeren en het onthouden van eerder gegeven commando's.

De standaard command interpreter voor UNIX is de Bourne shell, sh. Deze shell kan commando's interpreteren zoals hierboven is beschreven en kan daarnaast nog veel meer. Zo is het bij voorbeeld mogelijk meerdere commando's op één regel te geven, de in- en uitvoer van commando's aan elkaar te verbinden en commando's al dan niet te laten uitvoeren afhankelijk van de uitkomst van andere commando's. In feite zijn de commando's aparte programma's die door de shell aangeroepen worden. Daarnaast kent de shell nog een aantal interne commando's die hoofdzakelijk bedoeld zijn om de shell zelf te besturen.

De Bourne shell is niet de enige manier om commando's aan het systeem te geven. Behalve de Bourne shell is in de meeste UNIX distributies ook de C-shell, csh aanwezig. Dit is een command interpreter waarvan de syntax sterke overeenkomsten vertoont met de programmeertaal C. Verder biedt de C-shell met name voor interactief gebruik een aantal aantrekkelijke mogelijkheden die in de standaard (Bourne) shell niet aanwezig zijn. Voor het interpreteren van shell scripts wordt de C-shell echter zelden of nooit gebruikt. Hiervan zijn een aantal redenen aan te wijzen. In de eerste plaats is de C-shell niet in elke UNIX distributie aanwezig; de Bourne shell behoort standaard bij UNIX en is dus altijd aanwezig. Een shell script wat overdraagbaar moet zijn en dus op ieder willekeurig systeem geïnterpreteerd moet kunnen worden zal voor de Bourne shell geschreven zijn. Door de makers van UNIX (AT&T Bell Labs) wordt de C-shell dan ook niet ondersteund. In de tweede plaats is de C-shell aan de Berkeley universiteit ontwikkeld, in tegenstelling tot de Bourne shell welke een commercieel produkt is. De C-shell bevat daarom nogal wat bugs. Bij normaal gebruik zal men van deze bugs weinig of niets merken, maar in de manual page van csh staat: "Although robust enough for general use, adventures into the esoteric periphery of the C-shell may reveal unexpected quirks". Ondanks deze nadelen is de C-shell zeer aantrekkelijk voor interactief gebruik.

8.1 Standaard invoer en uitvoer

Verreweg de meeste programma's sturen informatie naar het beeldscherm van de terminal (of window) terwijl een groot aantal (interactieve) programma's invoer vanaf het toetsenbord van de terminal verwacht. Vanuit het programma gezien komt de invoer altijd uit een file en gaat de uitvoer ook altijd naar een file. Ieder proces heeft altijd drie files open wanneer het start: de standaard invoer (stdin), de standaard uitvoer (stdout) en de standaard fout uitvoer (stderr). De invoer, stdin wordt geopend voor lezen en is normaliter gekoppeld aan het toetsenbord van de terminal terwijl stdout en stderr voor schrijven geopend worden en beide naar het beeldscherm geredigeerd worden.

De shell kent de mogelijkheid om iedere invoer- of uitvoerfile van een proces aan een willekeurige file (of device) te koppelen door de speciale tekens '>' en '<' te interpreteren. In de eenvoudigste vorm kunnen de standaard invoer en standaard uitvoer aan een file (op de schijf) gekoppeld worden. Zo wordt met de uitdrukking

commando >filenaam
de standaard uitvoer die normaal naar het beeldscherm gaat in de file met de naam filenaam geschreven. De file wordt hierbij opnieuw gecreëerd. Dit houdt in dat wanneer de file reeds bestond, deze eerst leeg gemaakt wordt. Schrijf de uitvoer van ls naar een file met het commando:
% ls >lijst
%
De standaard fout uitvoer (stderr) wordt hiermee niet geredigeerd en blijft dus naar het beeldscherm gaan. De standaard invoer, kan uit een (reeds bestaande) file met de naam filenaam gelezen worden door de uitdrukking
commando <filenaam
te gebruiken. Zo kunnen we de file lijst die we net aangemaakt hebben weer gebruiken als invoer voor wc (Word Count) om het aantal regels te tellen:
% wc -l <lijst
      4
%
De file lijst wordt door wc gelezen en het aantal regels wordt op het scherm (de standaard uitvoer) afgedrukt.

Ook kunnen we de standaard uitvoer van een commando aan een al dan niet bestaande file toevoegen. Hiervoor herkent de shell de uitdrukking

commando >>filenaam
Bestaat de file filenaam nog niet, dan wordt deze alsnog aangemaakt. Geef bij voorbeeld het commando:
% ls >>lijst
%
De uitvoer van ls wordt hiermee achteraan aan de bestaande file lijst toegevoegd. We kunnen weer met wc zien of de file inderdaad gegroeid is:
% wc -l <lijst
      8
%
En zoals verwacht kon worden, is het aantal regels in lijst verdubbeld.

Behalve het redigeren van de in- en uitvoer van een proces naar een file, kan ook de uitvoer van een proces verbonden worden met de invoer van een ander proces. In zo'n geval spreken we van een pipeline. Een pipeline wordt geconstrueerd door op de commando regel de afzonderlijke commando's te scheiden met een verticale streep ('|') (om historische redenen kan hiervoor ook de '^' voor gebruikt worden). Om bij voorbeeld het aantal files in de huidige directory te tellen, kan de uitvoer van ls gebruikt worden. Als deze uitvoer vervolgens in wc (Word Count) gevoerd wordt, verschijnt het aantal regels en daarmee het aantal files op de standaard uitvoer:

% ls | wc -l
      4
%
Wanneer commando's in een pipeline geplaatst worden, wordt de uitvoer direct (via een interne buffer) met de invoer van het volgende proces verbonden. De processen in een pipeline draaien dus tegelijkertijd. Het spreekt vanzelf dat een pipeline niet tot twee commando's beperkt behoeft te blijven. In principe kan het aantal commando's willekeurig groot gemaakt worden. Bij voorbeeld:
% tbl hoofdstuk4 | eqn | nroff -ms | filter | lpr
genereert tabellen in een file die "hoofdstuk4" heet. Deze uitvoer gaat naar eqn om de mathematische tekens te verwerken waarna nroff het document formatteert. Tenslotte gaat het geformatteerde document via een filter naar lpr om het naar de printer te sturen. Deze pipeline bestaat dus uit vijf processen die allen tegelijkertijd draaien.

8.2 Shell parameters

Ook kunnen in de shell parameters (variabelen) gebruikt worden. Op verschillende manieren kunnen deze parameters een waarde krijgen welke dan weer in de uitvoering van een commando gebruikt kan worden. Een parameter heeft een naam waarmee deze aangesproken kan worden. Alle parameters (afgezien van een aantal speciale parameters, zie verderop) hebben een naam die bestaat uit een willekeurig aantal letters, cijfers of underscores ('_'). Het eerste teken moet dan wel een letter zijn. Het toekennen van een waarde aan een parameter is in de Bourne shell vrij eenvoudig. Door:

 naam=waarde
(let op: géén spaties!) krijgt de parameter naam de waarde waarde. Evenals de Bourne shell maakt de C-shell gebruik van variabelen. De manier waarop de variabelen een waarde toegekend krijgen (de syntax) is een klein beetje anders. Een shell variabele verkrijgt in de C-shell een waarde door middel van het commando:
 set naam = waarde
Hier mogen dus wel spaties voor en na het '='-teken staan. Geef in de Bourne shell het commando:
% kleur=rood
%
Of in de C-shell het commando:
% set kleur = rood
%
Je hebt dan een variabele met de naam kleur gedefinieerd en deze variabele de waarde rood gegeven. De parameter blijft dan gedefinieerd zolang de shell bestaat. De waarde van de parameter kan wel vervangen worden door er op de zelfde manier een nieuwe waarde aan toe te kennen. Ook kan een parameter expliciet verwijderd worden (de parameter is dan niet meer gedefinieerd) door middel van:
 unset naam
Om nu de waarde van zo'n parameter te gebruiken, wordt de naam voorafgegaan door een '$'. Geef nu het commando:
% echo $kleur
rood
%
De waarde van een parameter kan gebruikt worden door de uitdrukkingen $naam of ${naam}. Hierbij zijn de accolades alleen nodig wanneer de naam besloten is in een woord. Type om dit te testen de volgende commando's:
% echo $kleurtint
kleurtint: Undefined variable.
% echo ${kleur}tint
roodtint
%
Met de uitdrukking $kleurtint wordt de waarde van de parameter kleurtint bedoeld, terwijl met de uitdrukking ${kleur}tint de waarde "roodtint" gecreëerd wordt. Dit werkt in de Bourne shell op dezelfde manier als in de C-shell.

Aan ieder proces wat gestart wordt, wordt een omgeving (environment) meegegeven in de vorm van een lijst namen die een waarde hebben. In deze lijst heeft ieder element de vorm "NAAM=WAARDE" (zie environ(5)). In die zin lijkt een variabele in de environment sterk op een parameter in de shell. Het zijn echter twee totaal verschillende entiteiten, hoewel er wel een sterke relatie tussen bestaat. De environment variabelen zijn toegankelijk voor ieder proces wat vanuit de shell gestart wordt. De shell parameters kunnen alleen binnen de shell gebruikt worden. Met behulp van de environment variabelen is het dus mogelijk diverse instellingen aan programma's door te geven. Met het commando printenv kan een lijst van alle environment variabelen zichtbaar gemaakt worden:

% printenv
PATH=/sbin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/bin:/usr/ucb:.
COLUMNS=80
WINDOWID=6291469
EDITOR=vi
LOGNAME=arjen
MAIL=/usr/mail/arjen
DISPLAY=unix:0.0
SHELL=/usr/bin/ksh
HOME=/home/arjen
TERM=xterm
PWD=/home/arjen/HKU
TZ=:WET
LINES=24
%

De Bourne shell communiceert op verschillende manieren met de environment. Om te beginnen zoekt de Bourne shell tijdens het opstarten de environment af en creëert voor iedere variabele een parameter waaraan de zelfde waarde wordt gegeven. Wanneer de gebruiker de waarde van zo'n parameter wijzigt verandert de waarde van de environment variabele dus in principe niet! Wel kan de binding tussen de environment en de parameters in de shell versterkt worden, en wel door het export commando. Met bij voorbeeld:

  export KLEUR
wordt de shell parameter KLEUR gebonden aan de gelijkluidende variabele in de environment. Wordt nu de waarde van KLEUR in de shell veranderd, bij voorbeeld met:
  KLEUR=groen
dan verandert de waarde van de variabele KLEUR in de environment mee.

De C-shell heeft geen enkele relatie tussen shell parameters en environment variabelen. Ze zijn volkomen gescheiden. Er is dan ook een ander commando om environment variabelen te creëren. Er bestaat dus niet zoiets als export in de Bourne shell. Aan een environment variabele wordt in de C-shell een waarde toegekend met het commando:

 setenv var waarde
Let op: geen '=' teken ! Ook hier geldt weer dat er geen shell variabele is die er mee in verband staat. Wel kunnen zowel shell variabelen als environment variabelen op de zelfde manier aangesproken worden, namelijk door de naam vooraf te laten gaan door een '$'.

De shell kent een aantal speciale parameters die je niet zonder meer een waarde kunt geven. De namen van deze parameters zijn in de shell gereserveerd. De belangrijkste zijn de positionele parameters. De positionele parameters krijgen hun waarde voordat de shell gestart wordt. In de positionele parameters worden namelijk de argumenten opgeslagen van het commando waarmee de shell is aangeroepen. Met name bij het gebruik van shell scripts is dit van belang. Het kenmerk van een positionele parameter is zijn naam: dat kan slechts één enkel cijfer zijn. Er zijn dus in totaal tien positionele parameters, $0 tot en met $9. Met de speciale naam $* kunnen alle positionele parameters in één keer aangesproken worden. Dit geldt echter alleen voor de Bourne shell. De C-shell heeft hier een ander mechanisme voor. De C-shell heeft namelijk een mogelijkheid om een regel van meerdere woorden in een shell variabele te stoppen en deze ook apart aan te spreken. De naam van een variabele mag gevolgd worden door een index of een bereik van indices, omsloten door rechte haken ('[' en ']'). Geef de variabele zin bij voorbeeld een waarde met:

% set zin =  (Dit is een voorbeeld)
%
dan wordt met echo $zin[4] het vierde woord uit deze variabele, dus "voorbeeld" op het scherm getoond. Merk op dat het eerste woord de index 1 heeft. Het aantal woorden in een variabele kan verkregen worden met de uitdrukking: $#naam dus in het bovenstaande voorbeeld geeft dit het volgende resultaat:
% set zin = (Dit is een voorbeeld)
% echo $#zin
4
% echo $zin
Dit is een voorbeeld
% echo $zin[4]
voorbeeld
%
Hiermee vervalt de noodzaak voor de 'positionele parameters' zoals die in de Bourne shell gebruikt worden. De commando regel waarmee de shell is aangeroepen is namelijk opgeborgen in de shell variabele argv. De commando argumenten kunnen dus bereikt worden door de juiste indices op argv toe te passen.

Zoals reeds vermeld in het voorgaande zijn er behalve 0 tot en met 9 en * nog een vijftal speciale parameters die door de Bourne shell zelf een waarde verkrijgen. Deze parameters hebben dan ook speciale namen:

Behalve deze speciale parameters zijn er ook een aantal parameters met 'gewone' namen die door de shell gebruikt worden. Echter, wanneer deze eenmaal een waarde hebben wordt die waarde niet steeds door de shell aangepast. Wel worden de meeste parameters bij het starten van de shell genitialiseerd: Alle andere mogelijke namen zijn vrij te gebruiken. De belangrijke parameters PATH, PS1, PS2, MAILCHECK en IFS die door de shell gebruikt worden kunnen niet verwijderd worden.

Een groot aantal shell variabelen in de C-shell worden door de shell gebruikt en hebben dus een speciale betekenis. Hieronder vallen bij voorbeeld argv, cwd, mail en prompt. Voor een volledige lijst van de gebruikte variabelen en hun betekenis wordt verwezen naar de manual page van csh. Een aantal variabelen worden door de C-shell zelf ingesteld of hebben een min of meer vaste relatie met de environment. Bij het starten van de C-shell worden de variabelen argv, cwd, home, path, prompt, shell en status genitialiseerd. De C-shell kopieert de environment variabele USER naar de shell variabele user, TERM naar term en HOME naar home. Wanneer één van deze variabelen een andere waarde krijgt, wordt deze waarde automatisch ook aangepast in de bijbehorende environment variabele. De variabelen PATH en path worden op soortgelijke wijze behandeld. De speciale shell variabele cwd bevat altijd de huidige directory waarin de C-shell verkeert. Wanneer deze verandert, gaat de environment variabele PWD automatisch mee.

8.3 Shell scripts

Behalve het interpreteren van commando's die door de gebruiker vanaf het toetsenbord ingevoerd worden, kan de shell ook commando's vanuit een file interpreteren. De commando's in een dergelijke file vormen dan een programma wat door de shell uitgevoerd wordt. Zo'n file wordt ook wel een shell script genoemd. In de regel begint een shell script altijd met:

#!/bin/sh
Het systeem kan hieraan herkennen dat het een script is wat door sh geïnterpreteerd moet worden. Daarnaast moet je de execute permissie vlag van de shell-script file aan zetten met:
% chmod +x script
%
Je kunt dan de naam van de shell-script file als een commando intypen.

Om de mogelijkheden van een shell script te vergroten kent de shell een aantal woorden waarmee programma constructies gebouwd kunnen worden. Hiermee zijn lussen en beslissingsstructuren mogelijk. De Bourne shell kent vier van deze constructies: if, case, for en while. In principe zijn hiermee alle denkbare constructies te implementeren. De entiteiten die binnen deze constructies gebruikt worden zijn lists. In het eenvoudigste geval is een list een commando of een pipeline. Een list kan echter ook bestaan uit meerdere commando's of pipelines, gescheiden door ;, &, && of ||. Voor de exacte betekenis van deze tekens wordt verwezen naar de manual (sh(1)). Meer informatie betreffende het gebruik van shell scripts is te vinden in "Doing more with UNIX Beginner's Guide".

In een shell script kan de alternatieve opdracht gemplementeerd worden met de if. De formele definitie hiervan is:

 if list then list [ elif list then list ] ... [ else list ] fi
Hiermee zijn alle mogelijke combinaties aangeduid. De list die volgt op if wordt uitgevoerd en als de exit status hiervan gelijk is aan nul, met andere woorden als de list succesvol is beindigd, wordt de list die volgt op de eerste then uitgevoerd. Zo niet, dan wordt de list achter de elif uitgevoerd en, wanneer deze een exit status heeft gelijk aan nul, de list achter de daaropvolgende then, enzovoort. Gaat ook deze niet dan wordt de list achter else uitgevoerd.

Een meervoudige keuze is te maken met de case:

 case woord in [ patroon [ | patroon ] ... ) list ;; ] ...  esac
Hierdoor wordt de list uitgevoerd die staat bij het eerste patroon waarmee woord overeen komt. De manier waarop woord overeen moet komen met patroon is dezelfde als die voor het expanderen van wildcards gebruikt wordt.

Eén van de twee manieren om een lus te construeren is de for:

 for naam [ in woord ... ] do list done
Aan naam wordt telkens het volgende woord toegekend en list uitgevoerd. Dit gaat door totdat naam alle woorden uit de lijst gehad heeft. Wordt het gedeelte "in woord ..." weggelaten dan krijgt naam achtereenvolgens de inhouden van de positionele parameters.

De tweede manier om een lus te implementeren is de while:

 while list do list done
Hierdoor wordt herhaaldelijk de while list uitgevoerd en als de exit status van deze list gelijk is aan nul, wordt de do list uitgevoerd. Zodra de exit status van de while list niet gelijk is aan nul wordt de lus beindigd. Op de plaats van while kan het woord until gezet worden. In dat geval wordt de lus doorlopen zolang de exit status van de until list ongelijk is aan nul. De Bourne shell kent nog een aantal interne commando's die met name in shell scripts hun nut kunnen bewijzen. Uiteraard kunnen deze commando's ook gebruikt worden wanneer interactief met de shell gewerkt wordt. Een volledige lijst van interne commando's is te vinden in sh(1). De belangrijkste interne commando's zijn:

8.4 Alias en history

Eén van de meest krachtige mechanismen die het interactieve gebruik van de C-shell vergemakkelijken zijn de substituties die op ingevoerde commando regels uitgevoerd kunnen worden. De C-shell onderhoudt een lijst van woorden waarvoor één of meerdere commando's voor ingevuld worden: de alias lijst. Door gebruik te maken van aliases kunnen synoniemen gecreëerd worden voor commando's teneinde deze commando's af te korten of eenvoudiger uitdrukkingen te kunnen gebruiken voor gecompliceerde commando regels die anders telkens opnieuw ingevoerd zouden moeten worden. De aliases worden gemaakt of verwijderd door middel van twee (interne) commando's: alias en unalias. De C-shell houdt een lijst bij van alle aliases die gedefinieerd zijn. Het eerste woord van ieder commando wordt dan in die lijst opgezocht en, als het gevonden wordt, vervangen door de definitie van de alias. De definitie van de alias wordt behandeld alsof het de volgende invoer regel is. Een belangrijke implicatie hiervan is het feit dat history substituties (zie verderop) binnen een alias gebruikt kunnen worden. De invoer regel waarop de alias werd aangeroepen is dan te beschouwen als het 'vorige commando'. Wordt bij voorbeeld de alias "lm" als volgt gedefinieerd:

 alias lm 'ls -l !* | more'
Wordt in een alias definitie de uitdrukking "!*" gebruikt, dan worden de argumenten van het oorspronkelijke commando in de alias expansie ingevoegd. Wanneer aangeroepen, stuurt deze alias de uitvoer van ls(1) via een pipeline door more(1). Het alias commando zonder argumenten geeft een lijst van alle aliases:
% alias
bye     logout
cd      cd !*; set prompt=${host}:$cwd"[\\!]"-\>
d       dirs
dl      (dirs -l)
hi      history
j       jobs
jl      (jobs -l)
l       (ls -l)
la      (ls -FCa)
lf      (ls -CF)
ls      (ls -x)
lt      (ls -lt)
m       more
more    pg -n -p "--MORE--" -s
newterm set term = !*
po      popd
psname  ps -ef | egrep 'PID|!*'
pu      pushd
so      source
tag     vi -t !*
xt      (xterm -geom +10+265 &)
zz      suspend
%

De C-shell houdt ook een lijst bij van de meest recente commando's die (gedurende de tijd dat de shell draait) ingevoerd zijn, de history lijst. Hierdoor zijn nieuwe commando's te construeren door aan vorige commando's te refereren. Bij het invoeren van nieuwe commando's kan dan aan de commando's in deze lijst gerefereerd worden. Dit is met name handig wanneer \o"e'"\o"e'"n of meerdere commando's herhaaldelijk gegeven moeten worden. Deze situatie treedt vaak op wanneer programmatuur ontwikkeld wordt. Diverse malen wordt dan dezelfde lus van editen - compileren - testen doorlopen. Door het gebruik van de history lijst kan dan veel typewerk bespaard worden. Ook voor het corrigeren van kleine spelfouten kan de history lijst uitkomst bieden. Het is immers veel gemakkelijker om in te voeren wat er in het vorige commando veranderd moet worden dan om de complete regel opnieuw in te voeren. De kans om nieuwe fouten te maken wordt hierdoor ook verkleind.

Het spreekt vanzelf dat de lijst van vroegere commando's niet oneindig lang kan worden. Er is daarom een beperkte lijst waarin de meest recentelijk gegeven commando's in opgeslagen zijn. Wordt een nieuw commando gegeven, dan wordt dit vooraan de lijst toegevoegd terwijl het oudste commando, achteraan de lijst vervalt. Het nummer van het commando (history number) telt echter wel normaal door zodat een commando met het zelfde nummer geassocieerd blijft. Met het ingebouwde commando history is de volledige history lijst zichtbaar te maken:

% history
    29  cd ../src
    30  ls
    31  cd C++
    32  ls
    33  vi Xwindow.C
    34  vi makefile
    35  make Xtest
    36  ls -l
    37  a.out
    38  history
%
Het aantal commando's wat in de history lijst opgeslagen wordt is gelijk aan de waarde van de shell variabele "history".

Een referentie aan de history lijst wordt steeds begonnen met een '!'. Wat daarachter volgt bepaalt aan welk commando in de history lijst gerefereerd wordt. Met "!!" wordt bij voorbeeld het vorige commando bedoeld. Ook kan aan een commando met een bepaald history nummer gerefereerd worden, en wel met "!n", waarin n het (absolute) history nummer van het bedoelde commando is. Is n een negatief getal, dan wordt dit relatief opgevat, dat wil zeggen de huidige commando regel, minus n. Merk op dat hierover geen dubbelzinnigheid kan bestaan, aangezien het geen zin heeft te refereren aan een commando dat gegeven werd voordat de C-shell draaide of een commando dat in de toekomst gegeven gaat worden. Aan een commando kan ook gerefereerd worden door naar een string in de commando regel te zoeken. Met de uitdrukking "!string" wordt het meest recente commando gezocht wat begint met string. Het meest recente commando wat de string bevat wordt gezocht wanneer de uitdrukking "!?string" gebruikt wordt.

Bij gebruik van de hierboven genoemde uitdrukkingen wordt de volledige commando regel uit de history lijst opgehaald. Door het toepassen van zogenaamde word designators en modifiers is het echter mogelijk om gedeelten uit de commando regel te extraheren en hierop veranderingen aan te brengen. Voor een volledige beschrijving van deze (gecompliceerde) constructies wordt verwezen naar de manual page van csh. Voor het creëren van een nieuw commando uit het vorige commando, waarbij een string veranderd wordt is echter een vereenvoudigde constructie bedacht:

 ^oud^nieuw
De eerste keer dat in het vorige commando de string oud voor komt wordt deze vervangen door de string nieuw, alvorens het commando uitgevoerd wordt. De rest van de commando regel blijft ongewijzigd. Is bij voorbeeld het volgende commando gegeven:
 find /usr/peter -name test. -print
dan is het eenvoudiger om de substitutie:
 ^es^ex
uit te voeren dan het volledige commando:
 find /usr/peter -name text. -print
opnieuw in te voeren.

9 Process beheer

Aangezien UNIX multi-tasking werkt, draaien er meerdere processen tegelijkertijd in het werkgeheugen. Dit 'tegelijkertijd' moet iets ruimer gezien worden dan in het normale spraakgebruik gebruikelijk is. Op een processor kunnen uiteraard niet meerdere processen echt tegelijk draaien. In werkelijkheid schakelt de processor steeds periodiek (bij voorbeeld 60 keer per seconde) over op een ander proces. Het zou echter voor dit diktaat te ver voeren om dat mechanisme uitgebreid te bespreken. Hiervoor wordt verwezen naar de literatuur. Het operating system houdt in een tabel (de 'proces table') alle informatie betreffende de draaiende processen bij. In deze tabel wordt ieder proces geïdentificeerd met een nummer, zijn "process id".

9.1 De process table

Informatie over de processen die 'tegelijk' draaien kan verkregen worden met ps. Zonder argumenten laat ps alleen de processen zien die verbonden zijn met dezelfde terminal. Hier is een voorbeeld:

% ps
   PID TTY      TIME COMD
  3143 pts/3    0:33 ksh
  6804 pts/3    0:10 xcalc
 26140 pts/3    0:07 xpostit
  2084 pts/3    0:00 ps
%
Om alle processen te zien die in het systeem aanwezig zijn kun je de -e optie gebruiken. Hier is een (verkort) voorbeeld:
% ps -e
   PID TTY      TIME COMD
     0 ?        1:40 sched
     1 ?       40:14 init
     2 ?        1:46 pageout
     3 ?       12:19 fsflush
     4 ?        0:01 kmdaemon
   103 ?       11:13 cron
 12291 ?        0:01 lpNet
   167 ?        3:50 ttymon
 12286 ?        0:24 lpsched
   166 ?        0:38 inetd
   112 ?        0:01 rpcbind
   114 ?        0:01 rpc.rwal
   147 ?        0:00 smtpd
  6804 pts/3    0:11 xcalc
 25137 con9     0:01 xinit
 25141 ?        3:33 tvtwm
  1535 con9     0:04 ksh
 19418 ?        0:03 xdm
 22350 ?       10:47 xterm
 25142 ?        3:23 xclock
 26140 pts/3    0:07 xpostit
 25138 ?        0:00 sh
  2331 pts/3    0:00 ps
 22352 pts/1    0:52 ksh
%
De werkelijke lijst beslaat al snel zo'n 50 processen. Dit zijn allemaal programma's die tegelijkertijd in het systeem draaien. Het eertse process wat gestart wordt wanneer de computer aangezet wordt is init. Deze heeft altijd process id 1. init is de 'stamvader' van alle processen in het systeem. De andere processen die in de lijst te zien zijn zijn programma's die zorgen voor uitvoer naar de printer, voor verbindingen over het netwerk, electronic mail, het afhandelen van terminals en natuurlijk de processen die door gebruikers gestart zijn.

ps laat het process id als eerste zien, onder de kop PID. Verder laat ps per proces de terminal, indien aanwezig, onder TTY, de tot nu toe gebruikte processor tijd onder TIME en het commando wat het proces startte onder COMD zien. Meer informatie over de processen is te zien met de -f en de -l optie. Met deze opties worden onder andere de prioriteit van een proces, de gebruiker ('eigenaar'), de tijd dat het process gestart is en de hoeveelheid geheugenruimte zichtbaar. Hier is een voorbeeld:

% ps -f
     UID   PID  PPID  C    STIME TTY      TIME COMD
   arjen  3143  3140  3   Jan 27 pts/3    0:34 ksh
   arjen  6804  3143  0   Jan 31 pts/3    0:11 xcalc
   arjen  2342  3143 19 13:47:12 pts/3    0:00 ps -f
   arjen 26140  3143  0   Feb 16 pts/3    0:07 xpostit
% ps -l
 F S   UID   PID  PPID  C PRI NI     ADDR     SZ    WCHAN TTY      TIME COMD
10 S   101  3143  3140  2  30 24 401fca50    170 401fca00 pts/3    0:34 ksh
10 S   101  6804  3143  0  26 28 4027ce50    546  79241dc pts/3    0:11 xcalc
10 O   101  2343  3143 15  54 24 40217250    122          pts/3    0:00 ps
10 S   101 26140  3143  0  26 28 40205050    791  79241dc pts/3    0:07 xpostit
%
Voor de exacte betekenis van al deze informatie en nog meer opties wordt verwezen naar de manual page van ps.

9.2 Processen in voorgrond en achtergrond

Iedere keer wanneer je een commando intypt wordt er een process gestart. De shell wacht dan tot het process klaar is, waarna je een volgend commando kunt geven. Het process draait dan op de voorgrond. Geef het commando:

% sleep 1000
De shell gaat dan 1000 seconden lang wachten. sleep is een programma wat het gespecificeerde aantal seconden niets doet. Gedurende die tijd zal de shell geen ander commando accepteren. Je kunt de sleep stoppen door het intoetsen van ^Z (control-Z). Het process wordt daarmee niet beëindigd; alleen maar tijdelijk stil gelegd, zoals je met ps kunt zien:
% sleep 1000
^Z
Stopped
% ps
   PID TTY      TIME COMD
  3143 pts/3    0:34 ksh
  6804 pts/3    0:11 xcalc
  2389 pts/3    0:00 sleep
 26140 pts/3    0:07 xpostit
  2368 pts/3    0:02 csh
  2390 pts/3    0:00 ps
%
Je kunt het process nu in de achtergrond (de background ) zetten met het commando bg. Het process "sleep 1000" draait dan verder zonder dat de shell er op wacht. Je kunt nu weer gewoon commando's intypen terwijl het process in de achtergrond door gaat totdat het klaar is:
% bg
[1]    sleep 1000 &
%
Het is ook mogelijk een process ineens in de achtergrond te starten en wel door het commando te laten volgen door een '&' teken:
% sleep 1200 &
[2] 2391
Met ps kun je nu zien dat we twee maal het programma sleep in de achtergrond hebben draaien:
% ps
   PID TTY      TIME COMD
  3143 pts/3    0:34 ksh
  6804 pts/3    0:11 xcalc
  2389 pts/3    0:00 sleep
 26140 pts/3    0:07 xpostit
  2368 pts/3    0:02 csh
  2392 pts/3    0:00 ps
  2391 pts/3    0:00 sleep
%
Met het kill commando kun je een process voortijdig beëindigen. Hiervoor moet je het process id van het te beëindigen process als argument aan kill meegeven. In de uitvoer van ps kun je zien dat de eerste sleep het process id 2389 heeft. Beëindig nu dit process met:
% kill 2389
[1]    Terminated           sleep 1000
%
Het getal 2389 is natuurlijk een voorbeeld. In iedere situatie zal het systeem een ander process id aan een process toekennen. Kijk daarom altijd eerst met ps wat de nummers van je processen zijn. In feite stuurt kill een signal naar het process. Hoe het desbetreffende process op een signal reageert hangt helemaal van de aard van het process af. Een signal werkt als een interrupt. Het proces stopt met zijn normale bezigheden en start een procedure om het signal af te handelen. Als een proces niets anders specificeert, zal het als gevolg van een signal ophouden te bestaan (exit gaan). Er bestaan verschillende soorten signals. Welk signal naar een proces gestuurd wordt kan opgegeven worden door het nummer of de naam van het signal, voorafgegaan door een '-' als argument aan kill op te geven. Zonder nadere specificatie stuurt kill het TERM (terminate, 15) signal.

De namen van alle mogelijke signals zijn te zien met het commando kill -l

% kill -l
HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM USR1
USR2 CHLD LOST WINCH URG IO STOP TSTP CONT TTIN TTOU VTALRM PROF XCPU XFSZ
%
Het is mogelijk dat een proces het terminate signal opvangt of negeert. Er is echter één signal wat niet door een proces opgevangen of genegeerd kan worden. Dit is het KILL signal (9). Het commando
% kill -KILL pid
is dus een zekere methode om een proces te beëindigen. Wordt een signal gestuurd naar proces nummer 0, dan wordt naar alle processen in de process groep een signal gestuurd. Een proces groep wordt gevormd door alle processen, resulterend uit de huidige login. Het spreekt vanzelf dat alleen de eigenaar van een proces of de 'super-user' aan dat proces een signal mag sturen.

Met iedere commando serie (enkel commando, pipeline, etc.) wordt door de C-shell een job geassocieerd. Dit om de commando's bij te houden welke in de achtergrond draaien of gestopt zijn door een TSTP signal (bij voorbeeld omdat een control-Z of control-Y is gegeven). Wanneer een commando door gebruikmaking van het speciale teken '&' in de achtergrond gestart wordt, laat de C-shell het job nummer en de bijbehorende proces nummers zien als in:

% ls | wc &
[3] 2398 2399
%
Een lijst van de draaiende jobs kan verkregen worden met het (interne) commando jobs.
% jobs
[1]  + Running              sleep 1200
[2]  - Running              sleep 1000
%
De huidige job, dat is de job die het laatst in de achtergrond is gezet, wordt in deze lijst aangegeven met een '+'. Het is vrij eenvoudig aan draaiende jobs te refereren en wel met het '%'. Zo wordt met "%", "%+" of "%%" de huidige job en met "%-" de vorige job bedoeld. Aan een willekeurige job kan gerefereerd worden met de uitdrukking "%j", waarin j het nummer van de job kan zijn of een string waarmee de commando regel die de job opstartte begon. Deze commando regel moet met de string dan wel eenduidig bepaald zijn. Om bij voorbeeld job nummer 2 af te breken, kan het commando:
% kill -KILL %2
[2]    Killed               sleep 1000
%
gebruikt worden. Merk op dat kill in dit geval een intern commando van de C-shell is en niet het programma /bin/kill. Deze commando's zijn niet exact equivalent.

9.3 Automatisch starten van processen

Tot nu toe heb je alleen processen gestart terwijl je ingelogd bent. Het is echter ook mogelijk om programma's te laten draaien op een willekeurig ander tijdstip. Zelfs wanneer je niet ingelogd bent kun je het systeem nog werk voor je laten doen. Geef om dit te doen de volgende commando's:

% date
Tue Feb 22 14:55:26 MET 1994
% at 14:57
echo Dit komt van at.\fP
warning: commands will be executed using /usr/bin/sh
job 761925420.a at Tue Feb 22 14:57:00 1994
%
Kies voor het tijdstip wat je aan at opgeeft een tijdstip wat 1 of 2 minuten later is dan de huidige tijd die met date wordt aangegeven. at gaat dan op invoer vanaf het toetsenbord staan wachten. Type dan de commando's in die je op het aangegeven tijdstip wilt laten uitvoeren en sluit dit af met ^D (control-D). De uitvoer die door de met at gestarte processen geproduceerd wordt, zal met mail naar je toegezonden worden. Er verschijnt dus niets op het scherm. Kijk, wanneer het tijdstip voor at verstreken is naar de mail die je hebt ontvangen:
% mail
From arjen Tue Feb 22 14:57 MET 1994
To: arjen
Subject: Output from "at" job
From: arjen@ecl021.artmediatech.nl (Arjen Baart)
Date: Tue, 22 Feb 1994 14:57 MET
Content-Length: 100

Your "at" job "/var/spool/cron/atjobs/761925420.a" produced the following
 output :

Dit komt van at.

?
Je kunt met at dus éénmalig een process starten op een willekeurig tijdstip. Een nuttige toepassing hiervan is bij voobeeld het laten renderen van een animatie in het weekend. Een systeem wat hier enigszins op lijkt is cron. Hiermee kun je ook processen op aangegeven tijden starten, maar dan periodiek in plaats van éénmalig. Je kunt hetzelfde programma bij voorbeeld één keer per dag, één keer per week of twee keer per maand laten draaien. De programma's die periodiek uitgevoerd moeten worden staan in een speciale tabel. Iedere gebruiker heeft zo zijn eigen cron tabel. Met crontab kun je de inhoud van die tabel lezen of wijzigen. Geef het commando:
% crontab -l
0     4  *   *     0    find . -name core -exec rm {} \;
0    19  *   *   1-5    find . -mtime -1 -print|cpio -oBv|compress>/dev/dsk/fd0
%
en je ziet de inhoud van jouw cron tabel. Deze kan natuurlijk leeg zijn. Op iedere regel staan vijf velden, gescheiden door spaties, gevolgd door het commando wat op de aangegeven tijdstippen uitgevoerd moet worden. De eerste vijf velden geven de tijdstippen aan, en wel als volgt:
  1. minuten (0-59)
  2. uren (0-23),
  3. dag van de maand (1-31),
  4. maand van het jaar (1-12),
  5. dag van de week (0-6 met 0=zondag).
Op ieder van die velden kun je een lijst van getallen neerzetten. De getallen worden gescheiden door komma's. Een lijst van opeenvolgende getallen kun je verkort weergeven door de begin- en eindwaarde met een streepje er tussen. Zo is 3-15 hetzelfde als 3,4,5,6,7,8,9,10,11,12,13,14,15. Als alle mogelijke waarden gebruikt mogen worden in een bepaald veld, kun je dat aangeven met een sterretje. Zo heeft in het voorbeeld hierboven de eerste regel tot effekt dat iedere zondag om 04:00 uur alle "core" file opgezocht en verwijderd worden. De tweede regel zogt voor het maken van een backup en wel op iedere werkdag ("1-5" is maandag t/m vrijdag) om 19:00 uur. Om je cron tabel aan te passen moet je deze eerst naar een file schrijven, waarna je de tabel met vi kunt editen:
% crontab -l >cronjobs
% vi cronjobs
Voeg nu de volgende regel toe:
* * * * * echo Cron is still running.
Stuur vervolgens de cron tabel weer naar het cron systeem met:
% crontab cronjobs
%
Er wordt dan iedere minuut (ieder uur, iedere dag) het commando
echo Cron is still running.
uitgevoerd. Je krijgt dan ook iedere minuut met mail de volgende boodschap:
% mail
From arjen Tue Feb 22 15:19 MET 1994
To: arjen
From: arjen@ecl021.artmediatech.nl (Arjen Baart)
Subject: Output from "cron" command
Date: Tue, 22 Feb 1994 15:19 MET
Content-Length: 101

Your "cron" job

echo Cron is still running.

produced the following output:

Cron is still running.
?
Haal tenslotte het echo commando weer uit je cron tabel.