Werken met bash

>> Index <<

Wat is bash?

Bash is een opdrachtverwerkingsprogramma (command interpreter). Het is een programma dat uw opdrachten interpreteert en voor verwerking aan het besturingssysteem doorgeeft. Via de opdrachten die u aan bash doorgeeft zal de kernel programma's starten en stoppen. Onder UNIX spreekt men van shell: de interactieve gebruikersinterface (schil) rondom een centrale kern(el).

De bash schil wordt via het toetsenbord bediend. Bash is het analoog van command.com en cmd.exe van resp. DOS/Windows en Windows NT, 2000, XP en OS/2. Daarnaast bestaan er ook grafische schillen (X Window System, de Windows Explorer, OS/2 Presentation Manager) die met de muis en het toetsenbord worden bediend. Angelsaksische termen zijn resp. Command Line Interpreter of Interface (CLI) of Graphical User Interface (GUI), voor respectievelijk de tekstmodus en grafische schillen.

Eigenschappen van bash

Bash is de GNU Bourne-Again Shell. Het is de meest gebruikte shell onder Linux. Bash is de opvolger van de originele UNIX Bourne shell (sh), maar bevat ook elementen van de Korn (ksh) Tcsh en C shells (csh). Er zijn versies van bash voor andere besturingssystemen (o.a. Windows en OS/2).

Bash bevat vergeleken met de niet grafische DOS, Windows en OS/2 opdrachtverwerkingsprogramma's opvallend weinig interne opdrachten. Zo is er bijvoorbeeld geen interne kopieeropdracht. Bash maakt voor het kopiëren gebruik van het externe hulpprogramma /bin/cp. Dergelijke door de shell gebruikte hulpprogramma's bevinden zich in /bin en /sbin en de /usr varianten hiervan. Zoals u hieronder ziet bevindt bash zich in /bin (de voor de gebruikers beschikbare systeembestanden).

sjoerd@zolder:~> whereis bash
bash: /bin/bash /etc/bash.bashrc /usr/share/man/man1/bash.1.gz

Deze modulaire opbouw van een dunne schil met veel eveneens kleine hulpbestanden is een typisch voorbeeld van het KISH principe: Keep it Simple. Stupid. Maak van programma's geen alleskunners, maar uitwisselbare specialisten. Het feit dat bash nauwelijks interne opdrachten kent maakt het dan ook geen minder krachtig opdrachtverwerkingsprogramma. Integendeel. Het stelde de bash programmeurs in staat om de "core business" van de shell - het interpreteren en uitvoeren van uw opdrachten - te verfijnen. Zozeer dat onder UNIX shell programmering een serieuze bezigheid werd.

Door deze modulaire opbouw kan root (de systeembeheerder) de toegang tot en uitvoer van externe opdrachten (bijv. rm van remove) beperken. Bijv. door de hulpprogramma's naar een voor gewone gebruikers ontoegankelijke map (als /sbin) te verplaatsen. Zoiets lukt natuurlijk niet met een interne opdracht als del(ete) van cmd.exe, want hierover zal iedereen met shell toegang beschikken. Alleen de bestandspermissies kunnen u dan tegen een ongewenst wissen beschermen. Ook kan root de werking van een externe opdracht via een alias veranderen. Zo zou root als gebruiker www (dat kan een virus of hacker zijn) onverwacht een cp opdracht uitvoert, i.p.v. die opdracht uit te voeren, een mailtje naar de systeembeheerder kunnen sturen.


Vergeleken met deze gespecialiseerde (en uitwisselbare) open source opdrachtverwerker die met eenvoudige hulpprogramma's een goed gedocumenteerde en flexibele en complete programmeeromgeving vormt, vormt de grafische Explorer.exe van Windows met zijn ondoorzichtige bibliotheken een niet te omzeilen beveiligingsprobleem (Unchecked Buffer in Windows Shell).

Een ander praktisch voordeel van deze modulaire opbouw is dat u niet op een nieuwe shell (of een nieuw besturingssysteem) hoeft te wachten om die aanpassingen in de werkwijze van de shell uit te kunnen voeren.

Opdrachtverwerking

Wat valt er aan uw opdrachten te interpreteren? Een heleboel. Om te beginnen maakt iedere shell het onderscheid tussen interne een externe opdrachten. Een interne opdracht wordt door de opdrachtverwerker zelf uitgevoerd. Een externe opdracht wordt door een gelijkluidend programma of een symlink daarvan in een nieuwe shell (kindshell) uitgevoerd. Als u iets typt wordt eerst nagegaan of het een interne opdracht is. Interne (in de shell ingebakken) opdrachten worden onmiddellijk uitgevoerd. Blijkt uw commando geen interne opdracht te zijn, dan wordt in het pad nagekeken of er een externe opdracht bestaat die ermee overeenstemt. Is dat geval dan wordt ze uitgevoerd. De uitvoer (hier van make) kan ook een foutmelding zijn:

sjoerd@visser:/ > make love
make: *** No rule to make target `love'. Stop.

De parameter (argument) "love" wordt niet door het commando "make" begrepen.

Bash geeft zelf een foutmelding indien het programma (of een symlink daarvan) niet gevonden wordt.

sjoerd@visser:/ >fdisk
bash: fdisk: command not found

Fdisk zit niet in het pad van sjoerd. Alleen root mag dit systeemprogramma gebruiken. Want het bestaat wel:

sjoerd@visser:/ > whereis fdisk
fdisk: /sbin/fdisk /usr/share/man/man8/fdisk.8.gz

Bash laat ook aan elkaar gekoppelde opdrachten toe. Hierbij kan de uitvoer van het ene programma als invoer van een ander programma dienen (text streams). U kunt ze in een macro of shell script (verg. DOS batch) vastleggen.

Een shell script bestaat uit een of meer opdrachten met een inleidend commentaar. Net als in een programmeertaal kunt u allerlei voorwaarden aan de bewerkingen koppelen. Het script vormt dan een programma, waarbij de shell (bash, de interpreter) de shell eigen elementen (syntaxis) van het script in machinetaal vertaald (interpreteert).

Een eenvoudig shellscript begint met een commentaarregel (#!pad/shellnaam) die de betreffende shell aanroept. Alle commentaarregels beginnen met een hash teken (#, hekje).

#!/bin/sh
# commentaar
opdracht1
opdracht2

In dit geval gaat het om de met bash compatibele Bourne shell. Het bestand /bin/sh is doorgaans een symlink naar /bin/bash (niet *sh, maar -> bash in mc).

Opdrachtverwerking: Job control

In een multi-programming omgeving moet u niet alleen programma's kunnen starten, maar ook besturen. Dit aspect heet job-control.

Net als in een grafische (gevensterde) omgeving is er steeds maar een programma actueel. Dit programma draait op de voorgrond, accepteert de invoer uw toetsenbord en schrijft naar het scherm. De andere programma's draaien op de achtergrond.

Een opdracht start u op door de naam te typen. Hierbij kunt u gebruik maken van expansie van bestandsnamen met de TAB toets. Zo geeft f,TAB alle beschikbare opdrachten met een f.

sjoerd@laptop:~> f
factor filesize formail
.....etc
sjoerd@laptop:~> free
total used free shared buffers cached
Mem: 190896 186548 4348 0 12632 98372
-/+ buffers/cache: 75544 115352
Swap: 128480 0 128480
sjoerd@laptop:~>

Ik heb nog 4 MB geheugen vrij en niets geswapt.

Door een & teken achter de opdracht te plaatsen start u het programma op de achtergrond. Deze opdracht krijgt het opdrachtnummer (job control number) 1 van de shell en het Proces IDentification number (PID) 1515 van het systeem.

sjoerd@laptop:~> xosview &
[1] 1515
sjoerd@laptop:~>

Dit grafische programma start op de achtergrond en zoekt de X Server voor in- en uitvoer.

U krijgt een overzicht van de in de shell op de achtergrond lopende processen met de opdracht jobs. En met fg [opdrachtnummer] kunt u een opdracht naar de voorgrond (foreground) halen.

sjoerd@laptop:~> xterm &
[2] 1516
sjoerd@laptop:~> jobs
[1]- Running xosview &
[2]+ Running xterm &

Maar als ik xosview op de voorgrond zet raak ik de controle over de x terminal kwijt. Ls en help doen niets. Het X programma xosview is niet ontworpen om met een terminal te communiceren. Met Ctr-c breek ik dit ongewenste voorgrondproces af en komt de bash prompt weer in zicht.

sjoerd@laptop:~> fg 1
xosview
ls
help

sjoerd@laptop:~>

Jobs toont alleen de twee taken waar deze shell het beheer over heeft. Deze kinderprocessen zullen onderuit gaan als u de in de terminal lopende shell (hun ouderproces) sluit. De opdracht top geeft alle lopenden processen (ps -A(ll)). Tops interface is de krachtige less viewer (man less): u sluit top af met Ctr-c of q(uit). De actiefste processen staan bovenaan.

12:01am up 3:00, 5 users, load average: 0.00, 0.00, 0.00
77 processes: 76 sleeping, 1 running, 0 zombie, 0 stopped
CPU states: 0.5% user, 1.1% system, 0.0% nice, 98.2% idle
Mem: 190896K av, 187192K used, 3704K free, 0K shrd, 21320K buff
Swap: 128480K av, 776K used, 127704K free 85876K cached

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND
1652 sjoerd 16 0 988 988 768 R 1.3 0.5 0:00 top
1644 sjoerd 20 0 10352 9980 8476 S 0.3 5.2 0:01 kdeinit
1 root 20 0 220 220 188 S 0.0 0.1 0:03 init
2 root 20 0 0 0 0 SW 0.0 0.0 0:00 keventd
3 root 20 0 0 0 0 SW 0.0 0.0 0:00 kapmd
4 root 20 19 0 0 0 SWN 0.0 0.0 0:00 ksoftirqd_CPU0
5 root 20 0 0 0 0 SW 0.0 0.0 0:00 kswapd
6 root 2 0 0 0 0 SW 0.0 0.0 0:00 bdflush
7 root 20 0 0 0 0 SW 0.0 0.0 0:00 kupdated

Met kill [opdrachtnummer] kunt u een achtergrondopdracht vanaf de prompt sluiten. Gebruik hier het Proces ID dat ook top gebruikt. Het (relatieve) jobnummer van jobs is alleen voor de opdracht bg te gebruiken.

sjoerd@laptop:~> kill 2
bash: kill: (2) - Not owner
sjoerd@laptop:~> kill 1516
sjoerd@laptop:~> 
[2]+ Exit 15 xterm
sjoerd@laptop:~> 

Het daemonproces met Proces ID 2 (keventd) houdt zich bezig met de KDE GUI en draait met rootrechten.

Invoer en uitvoer van programma's

De klassieke UNIX utilities maken gebruik van drie kanalen. De kanalen zijn bestemd voor invoer van gegevens, uitvoer van (bewerkte) gegevens en voor uitvoer van foutmeldingen.

Kanaal

Standaardapparaat

Alternatieve in- en uitvoermethoden

0

Standaardinvoer (toetsenbord)

> naar bestand of >> aan bestand toevoegen of | naar programma doorvoeren.

1

Standaarduitvoer (beeldscherm)

> naar bestand of >> aan bestand toevoegen of | naar programma doorvoeren.

2

Standaardfoutuitvoer (beeldscherm)

> naar bestand of >> aan bestand toevoegen of | naar programma doorvoeren.

Het standaard invoerapparaat is het toetsenbord en het standaard uitvoerapparaat is het scherm. U bent dit al tegengekomen: wat u in bash typt (invoer), komt op het terminalvenster als uitvoer van bash en/of het door bash aangeroepen programma terug.

U kunt de standaard in- en uitvoer van programma's omleiden (redirectie).

sjoerd@laptop:~> dmesg

Toont de kernelbootberichten een voor een op het beeldscherm ( de standaarduitvoer van dmesg).

sjoerd@laptop:~> dmesg > /tmp/dmesg.txt

sjoerd@laptop:~> wc /tmp/dmesg.txt

193 1224 8474 /tmp/dmesg.txt

Dmesg voert de kernelberichten naar het bestand /tmp/dmesg.txt. Bij de enkele > wordt een bestaand bestand overschreven. Wordcount (wc) toont het aantal regels, woorden en bytes in /tmp/dmesg.txt op het scherm.

sjoerd@laptop:~> dmesg | wc

193 1224 8474

De uitvoer van dmesg gaat niet naar het scherm, maar wordt meteen door wordcount geteld. De uitvoer van dmesg wordt naar een geheugenbuffer geschreven, die door wordcount volgens het first-in-first-out (FIFO) principe wordt uitgelezen. De programma's worden verbonden door een benoemde pijp (|).

sjoerd@laptop:~> dmesg >> /tmp/dmesg.txt

sjoerd@laptop:~> wc < /tmp/dmesg.txt

386 2448 16948

sjoerd@laptop:~> dmesg >> /tmp/dmesg.txt

sjoerd@laptop:~> wc /tmp/dmesg.txt

579 3672 25422 /tmp/dmesg.txt

De >> voert de kernelbootberichten naar /tmp/dmesg.txt. Door de dubbele >> wordt de informatie aan het bestand toegevoegd. WC meet dubbele en na de derde keer driedubbele waarden.

sjoerd@laptop:~> cat /tmp/* 1>/dev/null

cat: /tmp/0510135660: Toegang geweigerd

cat: /tmp/0544062872: Toegang geweigerd

cat: /tmp/0725427735: Toegang geweigerd

etc...

Het pagineringsprogramma cat schrijft inhoud van een bestand op het scherm. Cat /tmp/* probeert de inhoud van alle bestanden in /tmp weer te geven. Dat levert foutmeldingen en gepiep op bij rootbestanden (en binaire bestanden) waarvan u geen leesrechten bezit (afsluiten met Ctrl-c). Maar door de standaard uitvoer (kanaal 1) niet op het scherm, maar naar de eeuwige bitvelden te sturen (1>/dev/null), ziet u alleen de foutmeldingen.

sjoerd@laptop:~> dmesg > dmesg.txt

De standaarduitvoer van een programma (het beeldscherm) kan via een pijplijn naar een ander programma worden doorgesluisd (prog1 | prog2), maar ook naar een bestand. Hierbij zal > een bestaand bestand overschrijven en zal >> de door dmesg gegenereerde output achteraan het bestand toevoegen.


De invoer van een programma kan een bestand (prog < cat bestandsnaam) of de uitvoer van een ander programma zijn: prog1 | prog2. De rechtopstaande verbindingsstreep symboliseert een pijpleiding (pipe). Hiermee kunnen de kernelbootberichten via dmesg | less als invoer voor de pagineringsprogramma (pagers) more of less en filters dienen. U kunt ze sorteren via sort of filteren (hier op de string mem) met find of grep.

sjoerd@laptop:~> dmesg | grep -i mem

Memory: 190208k/196544k available (1389k kernel code, 5948k reserved, 406k data, 120k init, 0k highmem)

Freeing initrd memory: 566k freed

Freeing unused kernel memory: 120k freed

sjoerd@laptop:~>

Zo weet ik dat de kernel al mijn 192 MB fysieke geheugen zag. Op bepaalde moederborden wordt het geheugen boven de 64 MB niet herkend en moet u lilo een mem=192 als bootoptie en/of beter append = mem=192 aan lilo.conf toevoegen (Zie: Linux on computers with more than 64 MByte RAM).



Parameters en variabelen

De meeste opdrachten accepteren meerdere argumenten. Meestal worden ze door opdracht --help aangeven.

De bash opstartbestanden

Een Bash login shell (bash die je vraagt in te loggen als in :bash -login) leest achtereenvolgens:

/etc/profile

Bevat instellingen voor alle gebruikers.

Overigens schrijft SuSE hier:

# PLEASE DON'T CHANGE /etc/profile. Chances are that your changes will be lost during the next upgrade. Use /etc/profile.local for your favourite global aliases, your VISUAL and EDITOR variables, etc ...

Dit is een waarschuwing dat SuSE /etc/profile voor zichzelf wil houden. SuSE biedt als alternatief het niet door een update overschreven /etc/profile.local aan. Deze moest ik echter wel zelf aanmaken.

In de home directory worden de volgende verborgen bestanden gelezen:

~/.bash_history

bevat de laatst door u gebruikte opdrachten

~/.profile

bevat login-scripts voor de individuele gebruikers en

~/.bashrc

bevat opdrachten als umask 022 en alias



Een niet login bash shell ("bash opdracht") leest alleen .bashrc, maar importeert de waarden uit de vorige shell.

Non-login, niet interactieve shells ( bash opdracht) lezen:

BASH-ENV


ENV


Dit is uit het boekje. SuSE zal afwijkingen van de regels in de betreffende configuratiebestanden opgeven.

De door u gebruikte shell kunt u opvragen met:

sjoerd@visser:~ > echo $SHELL
/bin/bash

Het door de shell gebruikte pad met:

sjoerd@visser:/ > echo $PATH
/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/var/lib/dosemu:/usr/games/bin:/usr/games:/opt/bin:/opt/gnome/bin:/opt/kde/bin:/usr/openwin/bin:.

De door de shell gebruikte omgevingsvariabelen met:

sjoerd@visser:~ > set
BASH=/bin/bash
BASH_VERSINFO=([0]="2" [1]="03" [2]="0" [3]="1" [4]="release" [5]="i686-pc-l
inux-gnu")
BASH_VERSION='2.03.0(1)-release'
COLORTERM=1
COLUMNS=76
DIRSTACK=()

Ik kapte ze af, want het zijn er heel veel.



Waarschuwing!

De beste manier om Linux te leren kennen is om de commando's gewoon uit te proberen. Doe dit echter nooit als root, maar als gebruiker! Maak eventueel als root een dummy user aan. In uw /home/dummy directory kunt u veilig experimenteren.

Expansie van bestandsnamen

Als u een of meer letters typt en tweemaal TAB toetst toont Bash de voor u beschikbare opdrachten die met die letters beginnen. Opdrachten worden afgemaakt (command completion):

sjoerd@visser:~ > k 
Display all 276 possibilities? (y or n) 
sjoerd@visser:~ > le 
less lessecho lesskey lesspipe.sh let lex 

Waarschijnlijk realiseert u zich hoeveel ongebruikte commando's er in een Linux systeem zitten. Linux applicaties hebben doorgaans een korte naam. De tab completion is vooral handig in combinatie met cd (change directory).

sjoerd@visser:/mnt/w95boot/Program\ Files > cd /m
bash: cd: /m: No such file or directory

cd /m levert niets op, maar cd /m[tab] wordt afgewerkt naar cd /mnt/. De bestandsnaam wordt geëxpandeerd:

sjoerd@visser:/mnt/w95boot/Program\ Files > cd /mnt/
sjoerd@visser:/mnt >

cd /mnt/w[tab] levert een keuzelijst op:

sjoerd@visser:/mnt/w95boot/Program\ Files > cd /mnt/w
w95 w95boot win

Met cd w95b[tab]/P[tab]{Enter} kom ik in Program Files. Let op de weergave van de spaties met een voorafgaande \.

sjoerd@visser:/mnt/w95boot > cd /mnt/w95boot/Program\ Files/
sjoerd@visser:/mnt/w95boot/Program\ Files > cd
sjoerd@visser:~ >

Daar heb ik nu niets te zoeken. cd zonder iets brengt me naar mijn Home (~) directory.



Hulp

Veel opdrachten tonen onder de parameter --help of --? een eenvoudig hulpscherm.

man opdracht is ook een manier om hulp in te roepen.

apropos steekwoordje geeft en lijst van manuals.

info bash geeft hulp in het hypertekst formaat over de bash prompt.

De standaard output gaat naar het scherm.

/dev/stderr 
/dev/stdin 

Toetsenbordmakro

Onder bash kunt als volgt een toetsenbordmakro opnemen.

Sneltoets

Let op: Het gaat om de hoofdletter X (Crtr-Shift-x).

Ctr-X, )

Makro opnemen

Crl-X, (

Makro-opname stoppen (geeft piep)

Ctr-X, e

Makro uitvoeren

Deze makro's zijn vooral handig als uw opdrachten meerdere regels beslaan. Een eenregelige opdracht is met het pijltje omhoog terug te vinden (bash history).

>> Index <<

Advanced Bash-Scripting Guide : An in-depth exploration of the art of shell scripting by Mendel Cooper.

Common Unix Commands

Frequently Used Unix Commands