En vigtig del af at lære at arbejde med Ubuntu, og Linux-distributioner generelt, involverer at få færdighed i at arbejde i shell-miljøet. Selv om de grafiske skrivebordsmiljøer som GNOME, der følger med Linux, giver en brugervenlig grænseflade til operativsystemet, giver shell-miljøet i praksis langt større muligheder, fleksibilitet og automatisering, end man nogensinde kan opnå ved hjælp af grafiske skrivebordsværktøjer. Shell-miljøet giver også mulighed for at interagere med styresystemet, når der ikke er et skrivebordsmiljø til rådighed, hvilket ofte sker, når man arbejder med et serverbaseret styresystem som Ubuntu eller et beskadiget system, der ikke vil starte helt op.

Målet med dette kapitel er derfor at give en oversigt over standard shell-miljøet på Ubuntu (specifikt Bash-shellen).

1.1 Hvad er en shell?

Shellen er et interaktivt kommandofortolkermiljø, inden for hvilket kommandoer kan indtastes ved en prompt eller indtastes i en fil i form af et script og udføres. Shellens oprindelse kan spores tilbage til de tidlige dage af UNIX-operativsystemet. Faktisk var shell’en i Linux’ tidlige dage, før indførelsen af grafiske skriveborde, den eneste måde, hvorpå en bruger kunne interagere med operativsystemet.

Der er blevet udviklet en række shell-miljøer i årenes løb. Den første bredt anvendte shell var Bourne-shellen, som blev skrevet af Stephen Bourne på Bell Labs.

En anden tidlig skabelse var C-shellen, som delte nogle syntaksmæssige ligheder med programmeringssproget C og indførte brugervenlighedsforbedringer som f.eks. kommandolinjeredigering og historik.

Korn-shell’en (udviklet af David Korn i Bell Labs) er baseret på funktioner fra både Bourne-shell’en og C-shell’en.

Den standard shell på Ubuntu er Bash-shell’en (forkortelse for Bourne Again SHell). Denne shell, som begyndte sit liv som en open source-version af Bourne-shellen, blev udviklet til GNU-projektet af Brian Fox og er baseret på funktioner fra både Bourne-shellen og C-shellen.

1.2 Få adgang til Shell

Fra GNOME-skrivebordsmiljøet kan shellprompten tilgås fra et Terminal-vindue ved at vælge indstillingen Aktiviteter i øverste bjælke, indtaste Terminal i søgelinjen og klikke på Terminal-ikonet.

Ved fjernlogning på en Ubuntu-server, f.eks. ved hjælp af SSH, bliver brugeren også præsenteret for en shellprompt. Detaljer om adgang til en fjernserver ved hjælp af SSH vil blive behandlet i kapitlet “Konfigurering af SSH-nøglebaseret autentifikation på Ubuntu”. Ved opstart af et serverbaseret system, hvor der ikke er installeret et skrivebordsmiljø, indtastes shell’en umiddelbart efter, at brugeren har afsluttet login-proceduren på den fysiske konsolterminal eller på den eksterne login-session.

1.3 Indtastning af kommandoer ved kommandoprompten

Kommandoer indtastes ved shell-kommandoprompten ved blot at skrive kommandoen og trykke på Enter-tasten. Mens nogle kommandoer udfører opgaver lydløst, vil de fleste vise en eller anden form for output, før de vender tilbage til prompten. F.eks. kan kommandoen ls bruges til at vise filerne og mapperne i den aktuelle arbejdskatalog:

$ ls

Desktop Dokumenter Downloads Musik Billeder Billeder Offentlige skabeloner Videoer

De tilgængelige kommandoer er enten indbygget i selve shell’en eller ligger på det fysiske filsystem. Placeringen på filsystemet af en kommando kan identificeres ved hjælp af kommandoen which. For eksempel for at finde ud af, hvor den eksekverbare ls-kommando befinder sig på filsystemet:

$ which ls alias ls='ls --color=auto' /usr/bin/ls

Det fremgår tydeligt, at ls-kommandoen befinder sig i mappen /usr/bin. Bemærk også, at der er konfigureret et alias, et emne, som vil blive behandlet senere i dette kapitel. Hvis du bruger kommandoen which til at finde stien til kommandoer, der er indbygget i shell’en, vil du få en meddelelse om, at den eksekverbare fil ikke kan findes. Hvis man f.eks. forsøger at finde placeringen af kommandoen history (som faktisk er indbygget i skallen i stedet for at eksistere som en eksekverbar fil på filsystemet), vil det resultere i et output, der ligner følgende:

$ 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 Få oplysninger om en kommando

Mange af de kommandoer, der er tilgængelige for Linux-shellen, kan virke kryptiske til at begynde med. Hvis du vil finde detaljerede oplysninger om, hvad en kommando gør, og hvordan du bruger den, skal du bruge man-kommandoen, der angiver navnet på kommandoen som et argument. Du kan f.eks. få mere at vide om kommandoen pwd:

$ man pwd

Når ovenstående kommando udføres, vises en detaljeret beskrivelse af kommandoen pwd. Mange kommandoer vil også give yderligere oplysninger, når de køres med kommandolinjeindstillingen -help:

$ wc --help

1.5 Bash-kommandolinje-redigering

De tidlige shell-miljøer gav ikke nogen form for muligheder for linjebearbejdning. Det betød, at hvis du opdagede en fejl i begyndelsen af en lang kommandolinje, du var ved at skrive, måtte du slette alle de efterfølgende tegn, rette fejlen og derefter indtaste resten af kommandoen igen. Heldigvis tilbyder Bash en lang række muligheder for redigering af kommandolinjen som skitseret i følgende tabel:

Tastsekvens Aktion
Ctrl-b eller Venstre pil Før markøren én position tilbage
Ctrl-f eller Højre pil Før markøren en position fremad
Slet Slet det aktuelle tegn under markøren
Backspace Slet tegn til venstre for markøren
Ctrl-_ Fjern forrige ændring (kan gentages for at fortryde alle tidligere ændringer)
Ctrl-a Flytter markøren til linjens begyndelse
Ctrl-e Flytter markøren til linjens slutning
Meta-f eller Esc og derefter f Flytter markøren et ord fremad
Meta-b eller Esc og derefter b Flytter markøren et ord tilbage
Ctrl-l Tøm skærmen for alt undtagen den aktuelle kommando
Ctrl-k Slet til slutningen af linjen fra den aktuelle cursorposition
Meta-d eller Esc og derefter d Fraser til slutningen af det aktuelle ord
Meta-DEL eller Esc og derefter DEL Fraser begyndelsen til det aktuelle ord
Ctrl-w Sletning fra den aktuelle markørposition til det foregående hvide felt

Tabel 9-1

1.6 Arbejde med Shell-historikken

Ud over funktioner til redigering af kommandolinjen tilbyder Bash-shell’en også understøttelse af kommandolinjehistorik. En liste over tidligere udførte kommandoer kan ses ved hjælp af kommandoen history:

$ history1ps2ls3ls –l /4ls5man pwd6man apropos

Dertil kommer, at Ctrl-p (eller pil op) og Ctrl-n (eller pil ned) kan bruges til at rulle frem og tilbage gennem tidligere indtastede kommandoer. Når den ønskede kommando fra historikken vises, trykkes på Enter-tasten for at udføre den.

En anden mulighed er at indtaste ‘!’-tegnet efterfulgt af de første par tegn i den kommando, der skal gentages, efterfulgt af Enter-tasten.

1.7 Filename Shorthand

Mange shell-kommandoer tager et eller flere filnavne som argumenter. For eksempel, for at vise indholdet af en tekstfil med navnet list.txt, ville kommandoen cat blive brugt som følger:

$ cat list.txt

Sådan kan indholdet af flere tekstfiler vises ved at angive alle filnavne som argumenter:

$ cat list.txt list2.txt list3.txt list4.txt

I stedet for at indtaste hvert enkelt navn, kan mønstermatchning bruges til at angive alle filer med navne, der matcher bestemte kriterier. For eksempel kan jokertegnet “*” bruges til at forenkle ovenstående eksempel:

$ cat *.txt

Overstående kommando vil vise indholdet af alle filer, der slutter med en .txt-udvidelse. Dette kan yderligere begrænses til alle filnavne, der begynder med list og slutter med .txt:

$ cat list*.txt

Match med enkelte tegn kan specificeres ved hjælp af ‘?’-tegnet:

$ cat list?.txt

1.8 Fuldstændiggørelse af filnavn og sti

I stedet for at indtaste et helt filnavn eller en hel sti, eller bruge mønstermatchning for at reducere mængden af indtastning, tilbyder shell’en funktionen til fuldførelse af filnavn. For at bruge filnavnekomplettering skal du blot indtaste de første par tegn i fil- eller stinavnet og derefter trykke to gange på Esc-tasten. Shell’en vil derefter supplere filnavnet for dig med det første fil- eller stinavn i mappen, der passer til de tegn, du har indtastet. Hvis du vil have en liste over mulige overensstemmelser, skal du trykke på Esc = efter indtastning af de første par tegn.

1.9 Omdirigering af input og output

Som tidligere nævnt udsender mange shell-kommandoer oplysninger, når de udføres. Som standard går dette output til en enhedsfil ved navn stdout, som i det væsentlige er det terminalvindue eller den konsol, som shell’en kører i. Omvendt modtager shell’en input fra en enhedsfil ved navn stdin, som som standard er tastaturet.

Output fra en kommando kan omdirigeres fra stdout til en fysisk fil på filsystemet ved hjælp af ‘>’-tegnet. Hvis du f.eks. vil omdirigere output fra en ls kommando til en fil med navnet files.txt, skal du bruge følgende kommando:

$ ls *.txt > files.txt

Når den er færdiggjort, vil files.txt indeholde en liste over filer i den aktuelle mappe. På samme måde kan indholdet af en fil føres ind i en kommando i stedet for stdin. For eksempel for at omdirigere indholdet af en fil som input til en kommando:

$ wc –l < files.txt

Overstående kommando vil vise antallet af linjer i filen files.txt.

Det er vigtigt at bemærke, at omdirigeringsoperatoren “>” opretter en ny fil eller afkorter en eksisterende fil, når den anvendes. For at tilføje til en eksisterende fil skal du bruge operatoren ‘>>’:

$ ls *.dat >> files.txt

Foruden standardoutput tilbyder shell’en også standardfejloutput ved hjælp af stderr. Mens output fra en kommando ledes til stdout, ledes eventuelle fejlmeddelelser, der genereres af kommandoen, til stderr. Det betyder, at hvis stdout er rettet til en fil, vil fejlmeddelelser stadig blive vist i terminalen. Dette er generelt den ønskede adfærd, selv om stderr også kan omdirigeres, hvis det ønskes ved hjælp af operatoren ‘2>’:

$ ls dkjfnvkjdnf 2> errormsg

Når kommandoen er afsluttet, vil en fejl, der rapporterer det faktum, at filen med navnet dkjfnvkjdnf ikke kunne findes, være indeholdt i filen errormsg.

Både stderr og stdout kan omdirigeres til den samme fil ved hjælp af operatoren &>:

$ ls /etc dkjfnvkjdnf &amp;&gt; alloutput

Når udførelsen er afsluttet, vil alloutput-filen både indeholde en liste over indholdet af mappen /etc og den fejlmeddelelse, der er forbundet med forsøget på at liste en ikke-eksisterende fil.

1.10 Arbejde med pipes i Bash-shellen

Ud over I/O-omdirigering tillader shell’en også, at output fra en kommando kan pipes direkte som input til en anden kommando. En pipe-operation opnås ved at placere tegnet “|” mellem to eller flere kommandoer på en kommandolinje. For f.eks. at tælle antallet af processer, der kører på et system, kan output fra ps-kommandoen pippes igennem til wc-kommandoen:

$ ps –ef | wc –l

Der er ingen grænse for antallet af pipe-operationer, der kan udføres på en kommandolinje. For eksempel for at finde antallet af linjer i en fil, der indeholder navnet Smith:

$ cat namesfile | grep Smith | wc –l

1.11 Konfiguration af aliaser

Når du bliver mere fortrolig med shell-miljøet, er det sandsynligt, at du ofte vil finde dig selv i at afgive kommandoer med de samme argumenter. For eksempel kan du ofte bruge kommandoen ls med l og t-indstillingerne:

$ ls –lt

For at reducere mængden af indtastning, der er involveret i udstedelse af en kommando, er det muligt at oprette et alias, der mapper til kommandoen og argumenterne. Hvis man f.eks. vil oprette et alias, således at indtastning af bogstavet l får kommandoen ls -lt til at blive udført, skal man bruge følgende anvisning:

$ alias l="ls –lt"

Indtastning af l ved kommandoprompten vil nu udføre den oprindelige anvisning.

1.12 Miljøvariabler

Shell-miljøvariabler giver midlertidig lagring af data og konfigurationsindstillinger. Shell’en selv opstiller en række miljøvariabler, som brugeren kan ændre for at ændre shell’ens opførsel. En liste over de aktuelt definerede variabler kan fås ved hjælp af env-kommandoen:

$ 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 måske mest nyttige miljøvariabel er PATH. Denne definerer de mapper, hvor shell’en vil søge efter kommandoer indtastet ved kommandoprompten, og i hvilken rækkefølge den vil gøre det. PATH-miljøvariablen for en brugerkonto på et nyinstalleret Ubuntu-system vil sandsynligvis være konfigureret som følger:

$ echo $PATH/home/demo/.local/bin:/home/demo/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/ bin:/usr/local/sbin:/usr/sbin

En anden nyttig variabel er HOME, som angiver den aktuelle brugers hjemmemappe. Hvis du f.eks. ønskede, at shell’en også skulle søge efter kommandoer i mappen scripts, der ligger i din hjemmemappe, ville du ændre PATH-variablen som følger:

$ export PATH=$PATH:$HOME/scripts

Den aktuelle værdi af en eksisterende miljøvariabel kan vises ved hjælp af kommandoen echo:

$ echo $PATH

Du kan oprette dine egne miljøvariabler ved hjælp af kommandoen export. For eksempel:

$ export DATAPATH=/data/files

Et nyttigt trick til at tildele output fra en kommando til en miljøvariabel involverer brugen af anførselstegn (`) omkring kommandoen. For eksempel for at tildele den aktuelle dato og det aktuelle klokkeslæt til en miljøvariabel kaldet NOW:

$ export NOW=`date`$ echo $NOWTue Apr 2 13:48:40 EDT 2020

Hvis der er indstillinger for miljøvariable eller alias, som du har brug for at få konfigureret, hver gang du går ind i shellmiljøet, kan de tilføjes til en fil i din hjemmemappe med navnet .bashrc. F.eks. er følgende .bashrc-fil konfigureret til at konfigurere DATAPATH-miljøvariablen og et 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 Skrivning af shellscripts

Så langt har vi udelukkende fokuseret på Bash-shellens interaktive karakter. Med interaktiv mener vi, at vi manuelt indtaster kommandoer ved prompten én efter én og udfører dem. Faktisk er dette kun en lille del af det, som shell’en er i stand til. Et af de mest kraftfulde aspekter af shell’en er vel at mærke muligheden for at oprette shell-scripts. Shell-scripts er i bund og grund tekstfiler, der indeholder sekvenser af instruktioner, som kan udføres i shell-miljøet for at udføre opgaver. Ud over muligheden for at udføre kommandoer tilbyder shell’en mange af de programmeringskonstruktioner såsom for- og do-sløjfer og if-angivelser, som du med rimelighed kan forvente at finde i et scriptingsprog.

Det er desværre ikke muligt at give en detaljeret oversigt over shell-scripting i dette kapitel. Der findes imidlertid mange bøger og webressourcer dedikeret til shell scripting, som yder emnet langt mere retfærdighed, end vi nogensinde kunne håbe på at opnå her. I dette afsnit vil vi derfor kun give en meget lille smagsprøve på shell-scripting.

Det første skridt i oprettelsen af et shell-script er at oprette en fil (i dette eksempel vil vi kalde den simple.sh) og tilføje følgende som den første linje:

#!/bin/sh

Den #! kaldes “shebang” og er en særlig sekvens af tegn, der angiver, at stien til den fortolker, der er nødvendig for at udføre scriptet, er det næste element på linjen (i dette tilfælde den eksekverbare sh, der ligger i /bin). Det kunne lige så godt være f.eks. /bin/csh eller /bin/ksh, hvis det var en af de to fortolkere, du ønskede at bruge.

Det næste skridt er at skrive et simpelt script:

#!/bin/shfor i in *do echo $idone

Det eneste dette script gør er at iterere gennem alle filerne i den aktuelle mappe og vise navnet på hver enkelt fil. Dette kan udføres ved at sende navnet på scriptet igennem som et argument til sh:

$ sh simple.sh

For at gøre filen eksekverbar (og dermed ophæve behovet for at sende den igennem til sh-kommandoen) kan chmod-kommandoen bruges:

$ chmod +x simple.sh

Når execute-bid’en er sat på filens tilladelser, kan den udføres direkte. For eksempel:

$ ./simple.sh

1.14 Opsummering

I dette kapitel i Ubuntu Essentials har vi taget en kort rundtur i Bash shell-miljøet. I en verden af grafiske skrivebordsmiljøer er det let at glemme, at den sande kraft og fleksibilitet i et styresystem ofte kun kan udnyttes ved at gå ned under den brugervenlige skrivebordsgrænseflade og bruge et shell-miljø. Desuden er kendskab til shell’en en nødvendighed, når man skal administrere og vedligeholde serverbaserede systemer, hvor desktop ikke er installeret, eller når man forsøger at reparere et system, der er beskadiget i en sådan grad, at desktop- eller Cockpit-grænsefladen ikke længere vil starte.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.