Ett skal är operativsystemets kommandotolk. Bash är mitt favoritskal, men alla Linuxskal tolkar de kommandon som användaren eller sysadminen skriver in till en form som operativsystemet kan använda. När resultaten returneras till skalprogrammet skickar det dem till STDOUT som, som standard, visar dem i terminalen. Alla skalprogram som jag känner till är också programmeringsspråk.

Funktioner som tabkomplettering, återkallande och redigering av kommandoraden och genvägar som alias bidrar alla till dess värde som ett kraftfullt skalprogram. Dess standardläge för kommandoradsredigering använder Emacs, men en av mina favoritfunktioner i Bash är att jag kan ändra det till Vi-läge för att använda redigeringskommandon som redan är en del av mitt muskelminne.

Hursomhelst, om du tänker på Bash enbart som ett skal, missar du mycket av dess verkliga kraft. När jag gjorde research för min självstudiekurs om Linux i tre volymer (som den här artikelserien bygger på) lärde jag mig saker om Bash som jag aldrig hade vetat under mina över 20 år av arbete med Linux. Några av dessa nya kunskapsbitar har att göra med dess användning som programmeringsspråk. Bash är ett kraftfullt programmeringsspråk som är perfekt utformat för användning på kommandoraden och i skalskript.

Denna serie i tre delar utforskar användningen av Bash som ett programmeringsspråk för kommandoradsgränssnitt (CLI). I den här första artikeln behandlas enkel kommandoradsprogrammering med Bash, variabler och kontrolloperatorer. I de andra artiklarna utforskas typer av Bash-filer, sträng-, numeriska och diverse logiska operatörer som ger logik för kontroll av exekveringsflödet, olika typer av skalutvidgningar samt for-, while- och until-slingor som möjliggör repetitiva operationer. De kommer också att titta på några kommandon som förenklar och stöder användningen av dessa verktyg.

Shell

Ett shell är en kommandotolk för operativsystemet. Bash är mitt favoritskal, men alla Linuxskal tolkar de kommandon som användaren eller sysadminen skriver in till en form som operativsystemet kan använda. När resultaten returneras till skalprogrammet visar det dem i terminalen. Alla skal som jag känner till är också programmeringsspråk.

Bash står för Bourne Again Shell eftersom Bash-skalet är baserat på det äldre Bourne-skalet som skrevs av Steven Bourne 1977. Det finns många andra skal, men dessa är de fyra som jag möter mest frekvent:

  • csh: C-shell för programmerare som gillar syntaxen i C-språket
  • ksh: C-shell för programmerare som gillar syntaxen i C-språket
  • ksh: Korn-skalet, skrivet av David Korn och populärt bland Unix-användare
  • tcsh: En version av csh med fler användarvänliga funktioner
  • zsh: Alla skal har inbyggda kommandon som kompletterar eller ersätter de kommandon som tillhandahålls av de centrala verktygen. Öppna skalets man-sida och leta upp avsnittet ”BUILT-INS” för att se vilka kommandon det tillhandahåller.

    Varje skal har sin egen personlighet och syntax. Vissa kommer att fungera bättre för dig än andra. Jag har använt mig av C-skalet, Korn-skalet och Z-skalet. Jag gillar fortfarande Bash-skalet mer än någon av dem. Använd det som fungerar bäst för dig, även om det kan kräva att du provar några av de andra. Lyckligtvis är det ganska lätt att byta skal.

    Alla dessa skal är programmeringsspråk samt kommandotolkar. Här är en snabb rundtur i några programmeringskonstruktioner och verktyg som är integrerade delar av Bash.

    Bash som programmeringsspråk

    De flesta sysadmins har använt Bash för att utfärda kommandon som vanligtvis är ganska enkla och okomplicerade. Men Bash kan gå längre än att skriva in enskilda kommandon och många sysadmins skapar enkla kommandoradsprogram för att utföra en rad uppgifter. Dessa program är vanliga verktyg som kan spara tid och arbete.

    Mitt mål när jag skriver CLI-program är att spara tid och arbete (dvs. att vara den lata sysadminen). CLI-programmen stödjer detta genom att lista flera kommandon i en viss sekvens som exekveras efter varandra, så att du inte behöver titta på hur ett kommando fortskrider och skriva in nästa kommando när det första är färdigt. Du kan gå och göra andra saker utan att hela tiden behöva övervaka varje kommando.

    Vad är ”ett program”?

    The Free On-line Dictionary of Computing (FOLDOC) definierar ett program som: ”De instruktioner som utförs av en dator, i motsats till den fysiska enhet på vilken de körs”. Princeton Universitys WordNet definierar ett program som: ”…en sekvens av instruktioner som en dator kan tolka och utföra…”. Wikipedia har också en bra artikel om datorprogram.

    Därmed kan ett program bestå av en eller flera instruktioner som utför en specifik, relaterad uppgift. En instruktion för ett datorprogram kallas också för en programförklaring. För sysadmins är ett program vanligtvis en sekvens av skalkommandon. Alla skal som finns tillgängliga för Linux, åtminstone de som jag känner till, har åtminstone en grundläggande form av programmeringsförmåga, och Bash, standardskalet för de flesta Linuxdistributioner, är inget undantag.

    I den här serien används Bash (eftersom det är så allestädes närvarande), men om du använder ett annat skal kommer de allmänna programmeringsbegreppen att vara desamma, även om konstruktionerna och syntaxen kan skilja sig något. Vissa skal kan ha stöd för vissa funktioner som andra inte har, men de ger alla en viss programmeringsförmåga. Skalprogram kan lagras i en fil för upprepad användning, eller så kan de skapas på kommandoraden vid behov.

    Enkla CLI-program

    De enklaste kommandoradsprogrammen är en eller två på varandra följande programförklaringar, som kan vara besläktade eller inte, som skrivs in på kommandoraden innan Enter-tangenten trycks in. Det andra uttalandet i ett program, om det finns ett, kan vara beroende av åtgärderna i det första, men behöver inte vara det.

    Det finns också en bit syntaktisk interpunktion som måste anges tydligt. När ett enskilt kommando skrivs in på kommandoraden avslutas kommandot med ett implicit semikolon (;) när man trycker på Enter-tangenten. När det används i ett CLI-skalprogram som skrivs in som en enda rad på kommandoraden måste semikolonet användas för att avsluta varje uttalande och skilja det från nästa. Det sista uttalandet i ett CLI-shellprogram kan använda ett explicit eller implicit semikolon.

    En del grundläggande syntax

    De följande exemplen förtydligar syntaxen. Det här programmet består av ett enda kommando med ett explicit terminator:

    $ echo "Hello world." ;
    Hello world.

    Det kanske inte verkar vara något stort program, men det är det första programmet jag stöter på med varje nytt programmeringsspråk jag lär mig. Syntaxen kan vara lite annorlunda för varje språk, men resultatet är detsamma.

    Låt oss utveckla detta triviala men allestädes närvarande program lite mer. Dina resultat kommer att skilja sig från mina eftersom jag har gjort andra experiment, medan du kanske bara har de standardkataloger och filer som skapas i kontots hemkatalog första gången du loggar in på ett konto via GUI-skrivbordet.

    $ 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

    Det låter lite vettigare. Resultaten är relaterade, men de enskilda programförklaringarna är oberoende av varandra. Lägg märke till att jag gillar att sätta mellanslag före och efter semikolonet eftersom det gör koden lite lättare att läsa. Prova det lilla CLI-programmet igen utan explicit semikolon i slutet:

    $ echo "My home directory." ; ls 

    Det är ingen skillnad i resultatet.

    Något om variabler

    Som alla programmeringsspråk kan Bash-skalet hantera variabler. En variabel är ett symboliskt namn som hänvisar till en specifik plats i minnet som innehåller ett värde av något slag. Värdet på en variabel kan ändras, dvs. den är variabel.

    Bash skriver inte variabler på samma sätt som C och relaterade språk, utan definierar dem som heltal, flyttal eller strängtyper. I Bash är alla variabler strängar. En sträng som är ett heltal kan användas i heltalsaritmetik, vilket är den enda typ av matematik som Bash kan utföra. Om mer komplex matematik krävs kan kommandot bc användas i CLI-program och skript.

    Variabler tilldelas värden och kan användas för att hänvisa till dessa värden i CLI-program och skript. Värdet för en variabel sätts med hjälp av dess namn men utan att föregås av ett $-tecken. Med tilldelningen VAR=10 sätts värdet för variabeln VAR till 10. Om du vill skriva ut värdet på variabeln kan du använda kommandot echo $VAR. Börja med textvariabler (dvs. icke-numeriska variabler).

    Bashvariabler blir en del av skalmiljön tills de återställs.

    Kontrollera det initiala värdet för en variabel som inte har tilldelats; det bör vara noll. Tilldela sedan ett värde till variabeln och skriv ut det för att verifiera dess värde. Du kan göra allt detta i ett enda CLI-program:

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

    Notera: Syntaxen för variabelto¨ mdelning är mycket strikt. Det får inte finnas några mellanslag på vardera sidan av likhetstecknet (=) i tilldelningsangivelsen.

    Den tomma raden anger att det ursprungliga värdet för MyVar är noll. Att ändra och ställa in värdet på en variabel görs på samma sätt. Det här exemplet visar både det ursprungliga och det nya värdet.

    Som nämnts kan Bash utföra heltalsaritmetiska beräkningar, vilket är användbart för att beräkna en referens till platsen för ett element i en array eller för att göra enkla matematiska problem. Det är inte lämpligt för vetenskapliga beräkningar eller något som kräver decimaler, till exempel finansiella beräkningar. Det finns mycket bättre verktyg för dessa typer av beräkningar.

    Här är en enkel beräkning:

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

    Vad händer när du utför en matematisk operation som resulterar i ett flyttal?

    Resultatet är det närmaste heltalet. Lägg märke till att beräkningen utfördes som en del av echo-instruktionen. Matematiken utförs före det omslutande eko-kommandot på grund av Bash-ordningen för företräde. Mer information finns på Bashs man-sida och sök på ”precedence.”

    Kontrolloperatörer

    Shellens kontrolloperatörer är en av de syntaktiska operatörerna för att enkelt skapa några intressanta kommandoradsprogram. Den enklaste formen av CLI-program är bara att rada ihop flera kommandon i en sekvens på kommandoraden:

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

    Dessa kommandon körs alla utan problem så länge inga fel uppstår. Men vad händer när ett fel inträffar? Du kan förutse och tillåta fel med hjälp av de inbyggda kontrolloperatörerna && och || Bash. Dessa två kontrolloperatorer ger viss flödeskontroll och gör det möjligt för dig att ändra sekvensen för kodutförandet. Semikolonet anses också vara en Bash-kontrolloperatör, liksom newline-tecknet.

    Operatorn && säger helt enkelt: ”Om kommando1 är lyckat, kör då kommando2. Om kommando1 misslyckas av någon anledning, hopps kommando2 över”. Syntaxen ser ut så här:

    command1 && command2

    Nu ska vi titta på några kommandon som skapar en ny katalog och – om det lyckas – gör den till nuvarande arbetskatalog (PWD). Se till att din hemkatalog (~) är PWD. Försök först i /root, en katalog som du inte har tillgång till:

    Felet utfärdades av kommandot mkdir. Du fick inget fel som visade att filen inte kunde skapas eftersom skapandet av katalogen misslyckades. Kontrolloperatorn && kände av returkoden som inte var noll, så touch-kommandot hoppades över. Genom att använda kontrolloperatorn && förhindras att touch-kommandot körs eftersom det fanns ett fel i skapandet av katalogen. Den här typen av flödeskontroll av kommandoradsprogram kan förhindra att fel förvärras och gör en riktig röra av saker och ting. Men det är dags att bli lite mer komplicerat.

    Med kontrolloperatorn || kan du lägga till ett annat programuttalande som körs när det inledande programuttalandet returnerar en kod som är större än noll. Den grundläggande syntaxen ser ut så här:

    command1 || command2 

    Denna syntax lyder: ”Om kommando1 misslyckas, utför kommando2”. Det innebär att om kommando1 lyckas, så hoppar man över kommando2. Prova detta genom att försöka skapa en ny katalog:

    Detta är exakt vad du förväntar dig. Eftersom den nya katalogen inte kunde skapas misslyckades det första kommandot, vilket resulterade i att det andra kommandot utfördes.

    Kombinationen av dessa två operatörer ger det bästa av båda. Syntaxen för kontrolloperatorer som använder viss flödeskontroll har denna allmänna form när kontrolloperatorerna && och || används:

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

    Denna syntax kan anges på följande sätt: ”Om kommandot1 avslutas med en returkod på 0, kör då kommandot2, annars kör kommandot3.” Prova det:

    Prova nu det sista kommandot igen med din hemkatalog i stället för /root-katalogen. Du kommer att ha behörighet att skapa den här katalogen:

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

    Syntaxen för kontrolloperatorer, som command1 && command2, fungerar eftersom varje kommando skickar en returkod (RC) till skalet som anger om det slutfördes framgångsrikt eller om det skedde någon typ av fel under utförandet. Enligt konvention indikerar en RC på noll (0) att kommandot har lyckats, och alla positiva tal indikerar någon typ av misslyckande. Vissa av de verktyg som sysadmins använder returnerar bara en ett (1) för att indikera ett misslyckande, men många använder andra koder för att indikera vilken typ av misslyckande som inträffade.

    Bash-skalvariabeln $? innehåller RC från det senaste kommandot. Denna RC kan mycket enkelt kontrolleras av ett skript, nästa kommando i en lista med kommandon eller till och med av sysadmin direkt. Börja med att köra ett enkelt kommando och kontrollera RC omedelbart. RC kommer alltid att vara för det senaste kommandot som kördes innan du tittade på det.

    RC är i det här fallet noll, vilket betyder att kommandot slutfördes framgångsrikt. Prova nu samma kommando i roots hemkatalog, en katalog som du inte har behörighet till:

    I det här fallet är RC två; det betyder att en icke-rootanvändare nekades behörighet att komma åt en katalog som användaren inte har behörighet till. Kontrolloperatörerna använder dessa RC för att göra det möjligt för dig att ändra sekvensen av programutförandet.

    Sammanfattning

    Denna artikel tittade på Bash som programmeringsspråk och utforskade dess grundläggande syntax samt några grundläggande verktyg. Den visade hur man skriver ut data till STDOUT och hur man använder variabler och kontrolloperatorer. I nästa artikel i den här serien behandlas några av de många logiska operatorer i Bash som styr flödet av instruktionsutförandet.

Lämna ett svar

Din e-postadress kommer inte publiceras.