Een shell is de opdrachtinterpreter voor het besturingssysteem. Bash is mijn favoriete shell, maar elke Linux-shell interpreteert de commando’s die door de gebruiker of systeembeheerder worden ingetypt in een vorm die het besturingssysteem kan gebruiken. Wanneer de resultaten worden teruggestuurd naar het shell programma, stuurt het deze naar STDOUT die ze, standaard, weergeeft in de terminal. Alle shells die ik ken zijn ook programmeertalen.

Functies zoals tab completion, command-line recall en editing, en snelkoppelingen zoals aliassen dragen allemaal bij aan zijn waarde als een krachtige shell. De standaardmodus voor het bewerken van de opdrachtregel maakt gebruik van Emacs, maar een van mijn favoriete functies van Bash is dat ik het kan wijzigen in de Vi-modus om bewerkingsopdrachten te gebruiken die al deel uitmaken van mijn spiergeheugen.

Als je Bash echter alleen als een shell ziet, mis je veel van zijn ware kracht. Tijdens het onderzoek voor mijn driedelige Linux zelfstudie cursus (waarop deze serie artikelen is gebaseerd), leerde ik dingen over Bash die ik nooit had geweten in de meer dan 20 jaar dat ik met Linux werk. Sommige van deze nieuwe dingen hebben te maken met het gebruik van Bash als programmeertaal. Bash is een krachtige programmeertaal, een die perfect is ontworpen voor gebruik op de commandoregel en in shell scripts.

Deze driedelige serie verkent het gebruik van Bash als een command-line interface (CLI) programmeertaal. In het eerste artikel wordt ingegaan op eenvoudige commandoregelprogrammering met Bash, variabelen en besturingsoperatoren. In de andere artikelen wordt ingegaan op typen Bash-bestanden, string-, numerieke en diverse logische operatoren die uitvoer-flow controlelogica bieden, verschillende typen shell-uitbreidingen en de for, while en until lussen die repeterende bewerkingen mogelijk maken. Ze zullen ook kijken naar enkele commando’s die het gebruik van deze tools vereenvoudigen en ondersteunen.

De shell

Een shell is de commando-interpreter voor het besturingssysteem. Bash is mijn favoriete shell, maar elke Linux shell interpreteert de commando’s die door de gebruiker of systeembeheerder worden ingetypt in een vorm die het besturingssysteem kan gebruiken. Wanneer de resultaten worden teruggestuurd naar het shell programma, geeft het deze weer in de terminal. Alle shells waarmee ik bekend ben, zijn ook programmeertalen.

Bash staat voor Bourne Again Shell omdat de Bash shell gebaseerd is op de oudere Bourne shell die in 1977 door Steven Bourne werd geschreven. Er zijn veel andere shells beschikbaar, maar dit zijn de vier die ik het vaakst tegenkom:

  • csh: De C shell voor programmeurs die van de syntax van de C taal houden
  • ksh: De Korn shell, geschreven door David Korn en populair bij Unix gebruikers
  • tcsh: Een versie van csh met meer gebruiksvriendelijke functies
  • zsh: De Z-shell, die veel functies van andere populaire shells combineert

Alle shells hebben ingebouwde commando’s die de commando’s van de kernhulpprogramma’s aanvullen of vervangen. Open de man page van de shell en zoek de “BUILT-INS” sectie om te zien welke commando’s hij biedt.

Elke shell heeft zijn eigen persoonlijkheid en syntax. Sommige zullen beter voor je werken dan andere. Ik heb de C shell, de Korn shell, en de Z shell gebruikt. Ik hou nog steeds meer van de Bash shell dan van een van hen. Gebruik degene die het beste werkt voor jou, hoewel je daarvoor misschien een aantal van de anderen moet proberen. Gelukkig is het vrij eenvoudig om van shell te veranderen.

Al deze shells zijn programmeertalen, maar ook commando interpreters. Hier volgt een korte rondleiding langs enkele programmeer constructies en tools die integraal onderdeel zijn van Bash.

Bash als programmeertaal

De meeste sysadmins hebben Bash gebruikt om commando’s in te geven die meestal vrij simpel en ongecompliceerd zijn. Maar Bash kan verder gaan dan het invoeren van enkelvoudige commando’s, en veel systeembeheerders maken eenvoudige opdrachtregelprogramma’s om een reeks taken uit te voeren. Deze programma’s zijn algemene hulpmiddelen die tijd en moeite kunnen besparen.

Mijn doel bij het schrijven van CLI programma’s is om tijd en moeite te besparen (oftewel, om de luie sysadmin te zijn). CLI programma’s ondersteunen dit door een aantal commando’s in een specifieke volgorde op te sommen die na elkaar worden uitgevoerd, zodat je niet op de voortgang van het ene commando hoeft te letten en het volgende commando hoeft in te voeren als het eerste klaar is. U kunt andere dingen gaan doen en hoeft niet voortdurend de voortgang van elk commando in de gaten te houden.

Wat is “een programma”?

Het Free On-line Dictionary of Computing (FOLDOC) definieert een programma als: “De instructies die door een computer worden uitgevoerd, in tegenstelling tot het fysieke apparaat waarop ze worden uitgevoerd.” Princeton University’s WordNet definieert een programma als: “…een opeenvolging van instructies die een computer kan interpreteren en uitvoeren…” Wikipedia heeft ook een goede entry over computerprogramma’s.

Daarom kan een programma bestaan uit een of meer instructies die een specifieke, gerelateerde taak uitvoeren. Een instructie voor een computerprogramma wordt ook wel een programmaverklaring genoemd. Voor sysadmins is een programma meestal een opeenvolging van shell commando’s. Alle shells die voor Linux beschikbaar zijn, tenminste die waarmee ik bekend ben, hebben op zijn minst een basale vorm van programmeermogelijkheid, en Bash, de standaard shell voor de meeste Linux distributies, is daarop geen uitzondering.

Terwijl deze serie Bash gebruikt (omdat die zo alomtegenwoordig is), zullen de algemene programmeerconcepten hetzelfde zijn, hoewel de constructies en de syntaxis enigszins kunnen verschillen. Sommige shells kunnen bepaalde functies ondersteunen die andere niet ondersteunen, maar ze bieden allemaal enige programmeermogelijkheid. Shell programma’s kunnen worden opgeslagen in een bestand voor herhaald gebruik, of ze kunnen worden gemaakt op de commandoregel wanneer dat nodig is.

Eenvoudige CLI programma’s

De eenvoudigste commandoregel programma’s zijn een of twee opeenvolgende programma uitspraken, die al dan niet gerelateerd kunnen zijn, die worden ingevoerd op de commandoregel voordat de Enter toets wordt ingedrukt. Het tweede statement in een programma, als dat er is, kan afhankelijk zijn van de acties van het eerste, maar dat hoeft niet zo te zijn.

Er is ook een stukje syntactische interpunctie dat duidelijk moet worden vermeld. Bij het invoeren van een enkel commando op de commandoregel, eindigt het commando met een impliciete puntkomma (;) door op de Enter toets te drukken. Bij gebruik in een CLI-shellprogramma dat als een enkele regel op de opdrachtregel wordt ingevoerd, moet de puntkomma worden gebruikt om elke instructie af te sluiten en te scheiden van de volgende. De laatste instructie in een CLI shell programma kan een expliciete of impliciete puntkomma gebruiken.

Enige basis syntax

De volgende voorbeelden zullen deze syntax verduidelijken. Dit programma bestaat uit een enkel commando met een expliciete afsluiter:

$ echo "Hello world." ;
Hello world.

Dat lijkt misschien niet veel van een programma, maar het is het eerste programma dat ik tegenkom bij elke nieuwe programmeertaal die ik leer. De syntaxis is misschien een beetje anders voor elke taal, maar het resultaat is hetzelfde.

Laten we dit triviale maar alomtegenwoordige programma een beetje uitbreiden. Uw resultaten zullen anders zijn dan de mijne omdat ik andere experimenten heb gedaan, terwijl u misschien alleen de standaard mappen en bestanden heeft die worden aangemaakt in de account home directory de eerste keer dat u inlogt op een account via de GUI desktop.

$ echo "My home directory." ; ls ;
My home directory.
chapter25 TestFile1.Linux dmesg2.txt Downloads newfile.txt softlink1 testdir6
chapter26 TestFile1.mac dmesg3.txt file005 Pictures Templates testdir
TestFile1 Desktop dmesg.txt link3 Public testdir Videos
TestFile1.dos dmesg1.txt Documents Music random.txt testdir1

Dat maakt een beetje meer zin. De resultaten zijn gerelateerd, maar de individuele programma statements zijn onafhankelijk van elkaar. Merk op dat ik graag spaties zet voor en na de puntkomma omdat het de code wat leesbaarder maakt. Probeer dat kleine CLI programma nog eens zonder expliciete puntkomma aan het eind:

$ echo "My home directory." ; ls 

Er is geen verschil in de uitvoer.

Ziets over variabelen

Zoals alle programmeertalen kan de Bash shell omgaan met variabelen. Een variabele is een symbolische naam die verwijst naar een specifieke plaats in het geheugen die een of andere waarde bevat. De waarde van een variabele is veranderlijk, d.w.z. het is variabel.

Bash typeert variabelen niet zoals C en verwante talen, waarbij ze worden gedefinieerd als gehele getallen, drijvende punten, of tekenreekstypes. In Bash zijn alle variabelen tekenreeksen. Een tekenreeks die een geheel getal is, kan worden gebruikt voor integer-aritmetiek, de enige vorm van wiskunde waartoe Bash in staat is. Als meer complexe wiskunde nodig is, kan het commando bc worden gebruikt in CLI-programma’s en scripts.

Variabelen krijgen waarden toegewezen en kunnen worden gebruikt om naar die waarden te verwijzen in CLI-programma’s en scripts. De waarde van een variabele wordt ingesteld met behulp van zijn naam, maar niet voorafgegaan door een $-teken. De toewijzing VAR=10 stelt de waarde van de variabele VAR in op 10. Om de waarde van de variabele af te drukken, kan je het statement echo $VAR gebruiken. Begin met tekst (d.w.z., niet-numerieke) variabelen.

Bash variabelen worden onderdeel van de shell omgeving totdat ze worden gede-set.

Controleer de initiële waarde van een variabele die niet is toegewezen; deze zou null moeten zijn. Wijs vervolgens een waarde toe aan de variabele en druk deze af om de waarde te verifiëren. U kunt dit alles doen in een enkel CLI-programma:

$ echo $MyVar ; MyVar="Hello World" ; echo $MyVar ;
Hello World
$

Note: De syntaxis van variabelentoekenning is zeer strikt. Er mogen geen spaties staan aan weerszijden van het gelijkheidsteken (=) in de toewijzingsverklaring.

De lege regel geeft aan dat de beginwaarde van MyVar null is. Het veranderen en instellen van de waarde van een variabele gebeurt op dezelfde manier. Dit voorbeeld toont zowel de oorspronkelijke als de nieuwe waarde.

Zoals gezegd kan Bash integer-aritmetische berekeningen uitvoeren, wat handig is voor het berekenen van een verwijzing naar de plaats van een element in een array of het doen van eenvoudige wiskundige problemen. Het is niet geschikt voor wetenschappelijk rekenwerk of iets dat decimalen vereist, zoals financiële berekeningen. Er zijn veel betere gereedschappen voor dat soort berekeningen.

Hier volgt een eenvoudige berekening:

$ Var1="7" ; Var2="9" ; echo "Result = $((Var1*Var2))"
Result = 63

Wat gebeurt er als u een wiskundige bewerking uitvoert die resulteert in een drijvend-kommagetal?

Het resultaat is het dichtstbijzijnde gehele getal. Merk op dat de berekening is uitgevoerd als onderdeel van het echo statement. Door de voorrangsvolgorde van Bash wordt de berekening uitgevoerd vóór de echo-opdracht die er deel van uitmaakt. Zie voor details de Bash man page en zoek op “precedence.”

Control operators

Shell control operators zijn een van de syntactische operatoren voor het eenvoudig maken van een aantal interessante command-line programma’s. De eenvoudigste vorm van een CLI-programma is gewoon een aantal commando’s achter elkaar zetten op de commandoregel:

command1 ; command2 ; command3 ; command4 ; . . . ; etc. ;

Die commando’s lopen allemaal zonder problemen, zolang er geen fouten optreden. Maar wat gebeurt er als er een fout optreedt? U kunt anticiperen op fouten en deze toestaan met de ingebouwde && en || Bash controle operatoren. Deze twee controle-operatoren bieden een zekere mate van flow control en stellen u in staat de volgorde waarin de code wordt uitgevoerd te wijzigen. De puntkomma wordt ook beschouwd als een Bash-controle-operator, net als het teken newline.

De &&-operator zegt eenvoudigweg: “Als opdracht1 succesvol is, voer dan opdracht2 uit. Als opdracht1 om welke reden dan ook mislukt, wordt opdracht2 overgeslagen.” Die syntax ziet er als volgt uit:

command1 && command2

Nu, kijk eens naar enkele commando’s die een nieuwe directory aanmaken en – als het lukt – er de huidige werkdirectory (PWD) van maken. Zorg ervoor dat je home directory (~) de PWD is. Probeer dit eerst in /root, een directory waar je geen toegang tot hebt:

De fout is opgetreden door het mkdir commando. U hebt geen fout ontvangen die aangeeft dat het bestand niet kon worden aangemaakt omdat het aanmaken van de directory is mislukt. De &&-bedieningsoperator merkte de retourcode van nul op, zodat de aanraakopdracht werd overgeslagen. Door de &&-besturingsoperator te gebruiken, wordt voorkomen dat de aanraakopdracht wordt uitgevoerd omdat er een fout is opgetreden bij het maken van de map. Dit type van command-line programma flow control kan voorkomen dat fouten zich opstapelen en er een echte puinhoop van maken. Maar het is tijd om iets ingewikkelder te worden.

Met de controle-operator || kunt u een ander programma-instructie toevoegen die wordt uitgevoerd wanneer de eerste programma-instructie een code groter dan nul teruggeeft. De basissyntax ziet er als volgt uit:

command1 || command2 

Deze syntaxis luidt: “Als opdracht1 mislukt, voer dan opdracht2 uit.” Dat houdt in dat als opdracht1 slaagt, opdracht2 wordt overgeslagen. Probeer dit eens door te proberen een nieuwe directory aan te maken:

Dit is precies wat u zou verwachten. Omdat de nieuwe directory niet kon worden gemaakt, mislukte het eerste commando, wat resulteerde in de uitvoering van het tweede commando.

Combinatie van deze twee operatoren biedt het beste van beide. De syntaxis van de besturingsoperator die gebruik maakt van enige flow control neemt deze algemene vorm aan wanneer de besturingsoperatoren && en || worden gebruikt:

preceding commands ; command1 && command2 || command3 ; following commands

Deze syntaxis kan als volgt worden gesteld: “Als opdracht1 eindigt met een retourcode van 0, voer dan opdracht2 uit, voer anders opdracht3 uit.” Probeer het:

Nu probeer je het laatste commando opnieuw met je home directory in plaats van de /root directory. U hebt toestemming om deze directory aan te maken:

$ Dir=~/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
$

De syntaxis van de controle-operator, zoals commando1 && commando2, werkt omdat elk commando een retourcode (RC) naar de commandoregel stuurt die aangeeft of het met succes is voltooid of dat er tijdens de uitvoering een of andere fout is opgetreden. Bij conventie geeft een RC van nul (0) succes aan, en elk positief getal een soort mislukking. Sommige van de hulpmiddelen die sysadmins gebruiken geven gewoon een één (1) terug om een mislukking aan te geven, maar veel hulpmiddelen gebruiken andere codes om aan te geven wat voor soort mislukking zich heeft voorgedaan.

De Bash shell variabele $? bevat de RC van het laatste commando. Deze RC kan heel eenvoudig worden gecontroleerd door een script, het volgende commando in een lijst met commando’s, of zelfs de sysadmin rechtstreeks. Begin met het uitvoeren van een eenvoudig commando en controleer onmiddellijk de RC. De RC is altijd voor het laatste commando dat liep voordat je keek.

De RC, in dit geval, is nul, wat betekent dat het commando succesvol is voltooid. Probeer nu hetzelfde commando in de home directory van root, een directory waarvoor je geen rechten hebt:

In dit geval is de RC twee; dit betekent dat de toegang geweigerd werd voor een niet-root gebruiker tot een directory waartoe de gebruiker geen toegang heeft. De control operators gebruiken deze RC’s om de volgorde van programma-uitvoering te veranderen.

Samenvatting

Dit artikel behandelde Bash als een programmeertaal en verkende de basissyntaxis en enkele basisgereedschappen. Het liet zien hoe je gegevens afdrukt naar STDOUT en hoe je variabelen en controle operatoren gebruikt. Het volgende artikel in deze serie behandelt enkele van de vele Bash logische operatoren die de stroom van instructie-uitvoering regelen.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.