En viktig del av att lära sig att arbeta med Ubuntu, och Linuxdistributioner i allmänhet, innebär att få färdigheter i att arbeta i skalmiljön. Även om de grafiska skrivbordsmiljöer som GNOME som ingår i Linux ger ett användarvänligt gränssnitt till operativsystemet, ger skalmiljön i praktiken mycket större möjligheter, flexibilitet och automatisering än vad som någonsin kan uppnås med hjälp av grafiska skrivbordsverktyg. Skalmiljön är också ett sätt att interagera med operativsystemet när en skrivbordsmiljö inte är tillgänglig, vilket är vanligt när man arbetar med ett serverbaserat operativsystem som Ubuntu eller ett skadat system som inte vill starta upp helt.
Målet med det här kapitlet är därför att ge en översikt över standardskalmiljön i Ubuntu (särskilt Bash-skalet).
1.1 Vad är ett skal?
Skalet är en interaktiv kommandotolk-miljö där kommandon kan skrivas in i en promptrumma eller föras in i en fil i form av ett skript och exekveras. Skalets ursprung kan spåras tillbaka till UNIX-operativsystemets tidiga dagar. I själva verket var skalet det enda sättet för en användare att interagera med operativsystemet under Linux tidiga dagar före införandet av grafiska skrivbord.
En mängd olika skalmiljöer har utvecklats under årens lopp. Det första allmänt använda skalet var Bourne shell, som skrevs av Stephen Bourne på Bell Labs.
En annan tidig skapelse var C shell som hade vissa syntaxlikheter med programmeringsspråket C och som införde användbarhetsförbättringar som redigering av kommandoraden och historik.
Korn shell (utvecklat av David Korn vid Bell Labs) bygger på funktioner som tillhandahålls av både Bourne shell och C shell.
Standard shell på Ubuntu är Bash shell (förkortning för Bourne Again SHell). Detta skal, som började som en open source-version av Bourne shell, utvecklades för GNU-projektet av Brian Fox och bygger på funktioner från både Bourne shell och C shell.
1.2 Att få tillgång till skalet
Från skrivbordsmiljön GNOME kan skalprompten nås från ett Terminal-fönster genom att välja alternativet Aktiviteter i den översta raden, skriva in Terminal i sökfältet och klicka på Terminal-ikonen.
När användaren loggar in på en Ubuntu-server på distans, t.ex. med hjälp av SSH, får han eller hon också se en skalprompt. Detaljer om åtkomst till en fjärrserver med hjälp av SSH behandlas i kapitlet ”Konfigurera SSH-nyckelbaserad autentisering på Ubuntu”. Vid uppstart av ett serverbaserat system i vilket en skrivbordsmiljö inte har installerats, kommer skalet in omedelbart efter att användaren har slutfört inloggningsproceduren vid den fysiska konsolterminalen eller vid fjärrinloggningssessionen.
1.3 Inmatning av kommandon vid kommandoprompten
Kommandon matas in vid skalets kommandoprompt helt enkelt genom att skriva in kommandot och trycka på Enter-tangenten. Medan vissa kommandon utför uppgifter tyst, visar de flesta någon form av utdata innan de återgår till prompten. Kommandot ls kan till exempel användas för att visa filerna och katalogerna i den aktuella arbetskatalogen:
$ ls
Desktop Documents Downloads Music Pictures Public Templates Videos
De tillgängliga kommandona är antingen inbyggda i själva skalet eller finns i det fysiska filsystemet. Var i filsystemet ett kommando finns kan identifieras med hjälp av kommandot which. Till exempel, för att ta reda på var det körbara kommandot ls finns i filsystemet:
$ which ls alias ls='ls --color=auto' /usr/bin/ls
Det är tydligt att kommandot ls finns i katalogen /usr/bin. Observera också att ett alias är konfigurerat, ett ämne som kommer att behandlas senare i det här kapitlet. Om du använder kommandot which för att hitta sökvägen till kommandon som är inbyggda i skalet kommer du att få ett meddelande om att den körbara filen inte kan hittas. Om man till exempel försöker hitta platsen för kommandot history (som faktiskt är inbyggt i skalet istället för att finnas som en körbar fil i filsystemet) kommer det att resultera i ett utdata som liknar följande:
$ which history/usr/bin/which: no history in (/home/demo/.local/bin:/home/demo/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin)
1.4 Att få information om ett kommando
Många av de kommandon som är tillgängliga för Linux-skalet kan verka kryptiska till en början. Om du vill få detaljerad information om vad ett kommando gör och hur du använder det använder du kommandot man och anger kommandots namn som ett argument. Om du till exempel vill veta mer om kommandot pwd:
$ man pwd
När ovanstående kommando utförs visas en detaljerad beskrivning av kommandot pwd. Många kommandon ger också ytterligare information när de körs med kommandoradsalternativet -help:
$ wc --help
1.5 Bash-kommandoradsredigering
Förra skalmiljöer erbjöd inte någon form av radredigeringsmöjligheter. Detta innebar att om du upptäckte ett fel i början av en lång kommandorad som du skrev var du tvungen att radera alla följande tecken, rätta till felet och sedan skriva in resten av kommandot på nytt. Lyckligtvis erbjuder Bash ett brett utbud av kommandoradsredigeringsalternativ som beskrivs i följande tabell:
Tangentsekvens | Aktion |
Ctrl-b eller Vänsterpil | Förflytta markören en position bakåt |
Ctrl-f eller högerpilen | Förflyttar markören en position framåt |
Släck | Släck det aktuella tecknet under markören |
Backspace | Tecknet till vänster om markören raderas |
Ctrl-_ | Undgå föregående ändring (kan upprepas för att ångra alla tidigare ändringar) |
Ctrl-a | Förflyttar markören till början av raden |
Ctrl-e | Förflyttar markören till slutet av raden |
Meta-f eller Esc och sedan f | Förflyttar markören ett ord framåt |
Meta-b eller Esc och sedan b | Förflyttar markören ett ord bakåt |
Ctrl-l | Rensa skärmen från allt utom det aktuella kommandot |
Ctrl-k | Släpp till slutet av raden från markörens aktuella position |
Meta-d eller Esc och sedan d | Släck till slutet av aktuellt ord |
Meta-DEL eller Esc och sedan DEL | Släck början av aktuellt ord |
Ctrl-w | Släck från aktuell markörposition till föregående vitrymd |
Tabell 9-1
1.6 Arbeta med skalet Historik
Förutom kommandoradsredigeringsfunktioner har Bash-skalet också stöd för kommandoradshistorik. En lista över tidigare utförda kommandon kan visas med hjälp av kommandot history:
$ history1ps2ls3ls –l /4ls5man pwd6man apropos
Det går dessutom att använda Ctrl-p (eller pil uppåt) och Ctrl-n (eller pil nedåt) för att bläddra fram och tillbaka genom tidigare inmatade kommandon. När det önskade kommandot från historiken visas trycker du på Enter-tangenten för att utföra det.
Ett annat alternativ är att skriva in tecknet ’!’ följt av de första tecknen i det kommando som ska upprepas följt av Enter-tangenten.
1.7 Filnamnsförkortning
Många skalkommandon tar ett eller flera filnamn som argument. För att till exempel visa innehållet i en textfil som heter list.txt används kommandot cat på följande sätt:
$ cat list.txt
På samma sätt kan innehållet i flera textfiler visas genom att ange alla filnamn som argument:
$ cat list.txt list2.txt list3.txt list4.txt
Istället för att skriva in varje namn kan mönstermatchning användas för att specificera alla filer med namn som motsvarar vissa kriterier. Jokertecknet ”*” kan till exempel användas för att förenkla exemplet ovan:
$ cat *.txt
Kommandot ovan visar innehållet i alla filer som slutar med ett .txt-tillägg. Detta kan begränsas ytterligare till alla filnamn som börjar med list och slutar med .txt:
$ cat list*.txt
Enkla teckenmatchningar kan specificeras med hjälp av ’?’-tecknet:
$ cat list?.txt
1.8 Komplettering av filnamn och sökväg
Istället för att skriva in ett helt filnamn eller en hel sökväg, eller att använda mönstermatchning för att minska antalet inmatningar, tillhandahåller skalet funktionen för komplettering av filnamn. För att använda filnamnskomplettering skriver du helt enkelt in de första tecknen i fil- eller sökvägsnamnet och trycker sedan på Esc-tangenten två gånger. Skalet kommer då att komplettera filnamnet åt dig med det första fil- eller sökvägsnamnet i katalogen som matchar de tecken du skrev in. Om du vill få en lista över möjliga matchningar trycker du på Esc = efter att ha skrivit in de första tecknen.
1.9 Omdirigering av in- och utdata
Som tidigare nämnts ger många skalkommandon ut information när de exekveras. Som standard går denna utdata till en enhetsfil som heter stdout som i huvudsak är terminalfönstret eller konsolen där skalet körs. Omvänt tar skalet emot indata från en enhetsfil som heter stdin, vilket som standard är tangentbordet.
Utdata från ett kommando kan omdirigeras från stdout till en fysisk fil i filsystemet med hjälp av tecknet ”>”. För att till exempel omdirigera utdata från ett ls kommando till en fil som heter files.txt krävs följande kommando:
$ ls *.txt > files.txt
När det är klart kommer files.txt att innehålla en lista över filer i den aktuella katalogen. På samma sätt kan innehållet i en fil matas in i ett kommando i stället för stdin. Till exempel, för att omdirigera innehållet i en fil som indata till ett kommando:
$ wc –l < files.txt
Ovanstående kommando kommer att visa antalet rader i filen files.txt.
Det är viktigt att notera att omdirigeringsoperatorn ”>” skapar en ny fil, eller avkortar en befintlig fil när den används. För att lägga till en befintlig fil använder du operatorn ’>>’:
$ ls *.dat >> files.txt
För att lägga till en befintlig fil använder skalet även standardfelutgång med hjälp av stderr. Medan utdata från ett kommando leds till stdout, leds eventuella felmeddelanden som genereras av kommandot till stderr. Detta innebär att om stdout är riktad till en fil kommer felmeddelanden fortfarande att visas i terminalen. Detta är i allmänhet det önskade beteendet, men stderr kan också omdirigeras om så önskas med hjälp av operatorn ”2>”:
$ ls dkjfnvkjdnf 2> errormsg
När kommandot avslutas kommer ett fel som rapporterar det faktum att filen med namnet dkjfnvkjdnf inte kunde hittas att finnas i filen errormsg.
Både stderr och stdout kan omdirigeras till samma fil med hjälp av operatören &>:
$ ls /etc dkjfnvkjdnf &> alloutput
När exekveringen är avslutad kommer alloutputfilen att innehålla både en lista över innehållet i katalogen /etc och felmeddelandet i samband med försöket att lista en icke-existerande fil.
1.10 Arbeta med pipes i Bash Shell
Inom I/O-omdirigering tillåter skalet också att utdata från ett kommando kan pipas direkt som indata till ett annat kommando. En pipe-operation uppnås genom att placera tecknet ”|” mellan två eller flera kommandon på en kommandorad. För att till exempel räkna antalet processer som körs på ett system kan utdata från ps-kommandot ledas genom en pipeline till wc-kommandot:
$ ps –ef | wc –l
Det finns ingen begränsning för hur många pipe-operationer som kan utföras på en kommandorad. För att till exempel hitta antalet rader i en fil som innehåller namnet Smith:
$ cat namesfile | grep Smith | wc –l
1.11 Konfigurera alias
När du blir van vid skalmiljön är det troligt att du ofta kommer att få uppleva att du utfärdar kommandon med samma argument. Till exempel kan du ofta använda kommandot ls med alternativen l och t:
$ ls –lt
För att minska mängden skrivande vid utfärdandet av ett kommando är det möjligt att skapa ett alias som mappar till kommandot och argumenten. Om man till exempel vill skapa ett alias så att om man skriver in bokstaven l kommer kommandot ls -lt att exekveras, kan man använda följande uttalande:
$ alias l="ls –lt"
Om man skriver in l vid kommandoprompten kommer nu det ursprungliga uttalandet att exekveras.
1.12 Miljövariabler
Miljövariabler i shell ger tillfällig lagring av data och konfigurationsinställningar. Själva skalet ställer in ett antal miljövariabler som kan ändras av användaren för att ändra skalets beteende. En lista över för närvarande definierade variabler kan erhållas med kommandot env:
$ envSSH_CONNECTION=192.168.0.19 61231 192.168.0.28 22MODULES_RUN_QUARANTINE=LD_LIBRARY_PATHLANG=en_US.UTF-8HISTCONTROL=ignoredupsHOSTNAME=demo-pc.ebookfrenzy.comXDG_SESSION_ID=15MODULES_CMD=/usr/share/Modules/libexec/modulecmd.tclUSER=demoENV=/usr/share/Modules/init/profile.shSELINUX_ROLE_REQUESTED=PWD=/home/demoHOME=/home/demoSSH_CLIENT=192.168.0.19 61231 22SELINUX_LEVEL_REQUESTED= ...
Den kanske mest användbara miljövariabeln är PATH. Den definierar de kataloger i vilka skalet ska söka efter kommandon som skrivs in i kommandotolken, och i vilken ordning det ska göra det. Miljövariabeln PATH för ett användarkonto på ett nyinstallerat Ubuntu-system kommer troligen att konfigureras på följande sätt:
$ echo $PATH/home/demo/.local/bin:/home/demo/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/ bin:/usr/local/sbin:/usr/sbin
En annan användbar variabel är HOME som anger hemkatalogen för den aktuella användaren. Om du till exempel vill att skalet även ska leta efter kommandon i skriptkatalogen som ligger i din hemkatalog skulle du ändra PATH-variabeln på följande sätt:
$ export PATH=$PATH:$HOME/scripts
Det aktuella värdet för en befintlig miljövariabel kan visas med hjälp av kommandot echo:
$ echo $PATH
Du kan skapa dina egna miljövariabler med hjälp av kommandot export. Till exempel:
$ export DATAPATH=/data/files
Ett användbart knep för att tilldela utdata från ett kommando till en miljövariabel innebär att man använder backcotes (`) runt kommandot. Om du till exempel vill tilldela det aktuella datumet och klockan till en miljövariabel som heter NOW:
$ export NOW=`date`$ echo $NOWTue Apr 2 13:48:40 EDT 2020
Om det finns inställningar för miljövariabler eller alias som du behöver konfigurera varje gång du går in i skalmiljön, kan de läggas till i en fil i din hemkatalog som heter .bashrc. Följande .bashrc-fil är till exempel konfigurerad för att ställa in miljövariabeln DATAPATH och ett alias:
# .bashrc # Source global definitionsif ; then . /etc/bashrcfi # User specific environmentPATH="$HOME/.local/bin:$HOME/bin:$PATH"export PATH # Uncomment the following line if you don't like systemctl's auto-paging feature:# export SYSTEMD_PAGER= # User specific aliases and functionsexport DATAPATH=/data/filesalias l="ls -lt"
1.13 Att skriva skalskript
Sedan tidigare har vi enbart fokuserat på Bash-skalets interaktiva karaktär. Med interaktiv menar vi att manuellt skriva in kommandon i prompten ett efter ett och exekvera dem. I själva verket är detta bara en liten del av vad skalet kan göra. En av de mest kraftfulla aspekterna av skalet är utan tvekan möjligheten att skapa skalskript. Skalskript är i huvudsak textfiler som innehåller sekvenser av uttalanden som kan exekveras i skalmiljön för att utföra uppgifter. Förutom möjligheten att utföra kommandon tillhandahåller skalet många av de programmeringskonstruktioner som du rimligen kan förvänta dig att hitta i ett skriptspråk, t.ex. for- och do-slingor och if-satser.
En detaljerad översikt över skript i skalet ligger tyvärr utanför det här kapitlets räckvidd. Det finns dock många böcker och webbresurser som ägnas åt shell scripting och som gör ämnet mycket mer rättvisa än vad vi någonsin kan hoppas på att åstadkomma här. I det här avsnittet kommer vi därför bara att ge ett mycket litet smakprov på shell scripting.
Det första steget i att skapa ett shell script är att skapa en fil (i det här exemplet kommer vi att kalla den simple.sh) och lägga till följande som första rad:
#!/bin/sh
Den #! kallas ”shebang” och är en speciell sekvens av tecken som anger att sökvägen till den tolk som behövs för att exekvera skriptet är nästa punkt på raden (i det här fallet den exekverbara sh som finns i /bin). Det kan lika gärna vara till exempel /bin/csh eller /bin/ksh om någon av dem är den tolk du vill använda.
Nästa steg är att skriva ett enkelt skript:
#!/bin/shfor i in *do echo $idone
Allt det här skriptet gör är att iterera genom alla filer i den aktuella katalogen och visa namnet på varje fil. Detta kan exekveras genom att skicka skriptets namn som ett argument till sh:
$ sh simple.sh
För att göra filen exekverbar (vilket gör att den inte behöver skickas till sh-kommandot) kan chmod-kommandot användas:
$ chmod +x simple.sh
När biten exekvera har satts på filens behörigheter kan den exekveras direkt. Till exempel:
$ ./simple.sh
1.14 Sammanfattning
I det här kapitlet i Ubuntu Essentials har vi gjort en kort rundtur i skalmiljön Bash. I en värld av grafiska skrivbordsmiljöer är det lätt att glömma att den verkliga kraften och flexibiliteten i ett operativsystem ofta bara kan utnyttjas genom att gå ner under det användarvänliga skrivbordsgränssnittet och använda en skalmiljö. Att känna till skalet är dessutom en nödvändighet när man måste administrera och underhålla serverbaserade system som inte har skrivbordet installerat eller när man försöker reparera ett system som är skadat till den grad att skrivbordet eller Cockpit-gränssnittet inte längre startar.