linux3del1.mp4
(03:40) Demo: Shell-variabler
linux3del2.mp4
(05:32) Demo: Globale shell-variabler
linux3del3.mp4
(02:12) Demo: Hvor ligger alle kommandoene egentlig? Svar: PATH
linux3del4.mp4
(05:11) Demo: Prosesser
linux3del5.mp4
(08:05) Demo: Apostrofer og å tilordne output fra kommando til en variabel
linux3del6.mp4
(04:22) Demo: Omdirigering
linux3del7.mp4
(10:37) Demo: Omdirigering til og fra filer
linux3del8.mp4
(06:02) Demo: Omdirigering til og fra kommandoer; pipes
linux3del9.mp4
(1:07) Demo: Piping av standard error
linux3del10.mp4
(04:03) Demo: Sub-shell
linux3del11.mp4
(04:02) Demo: source
$ os=Linux $ dato='Thu Jan 25' |
Det må ikke være mellomrom før og etter =. Variabler refereres til med et $-tegn foran navnet:
$ echo $os Linux $ echo $dato Thu Jan 25 |
Navnet kan avgrenses med
$ echo $osfrelst $ echo ${os}frelst Linuxfrelst |
Kommandoer for å liste og fjerne variabler:
$ set # Lister alle definerte variabler og funksjoner $ unset os # Fjerner definisjonen av os |
export
:
$ date='30. januar' $ os=Linux $ export os $ export nyglobal='ny global verdi' |
Variabelene $os
og nyglobal
er nå globale og vil arves av nye shell som startes, men det vil
ikke $date
:
$ bash $ echo $os Linux $ echo $nyglobal ny global verdi $ echo $date |
men som vi ser kjenner det nye shellet ikke til variabelen $date
, den er lokal og
bare kjent i shellet den ble definert i.
export
$ export os=Linux
$ env
lister alle definerte globale variabler
$PATH
er en global variabel som inneholder en streng med alle mapper
(separert med kolon) som shellet leter i for å finne kjørbare filer når et
kommandonavn tastes inn til shellet
studssh$ echo $PATH /opt/bin:/local/iu/bin:/local/gnu/bin:/local/bin:/usr/X11R6/bin:/usr/bin:/bin:.: studssh$ type ls # type gir hvilket program shellet starter ls is /bin/ls |
Når du taster inn
$ ls |
leter bash igjennom alle mappene i $PATH
etter en fil med navn ls
helt til
det finner en i den nest siste (/bin
) og kjører den.
Hvis du gjør PATH tom:
$ PATH="" |
vil shellet ikke finne vanlige kommandoer som mv
og ls
fordi mappen /bin
ikke er med i $PATH
.
Hver gang vi starter et program lager Linux en uavhengig prosess:
$ emacs
Starter vi fra et shell, venter shellet på at programmet skal bli ferdig.
$emacs&
$
Dette starter emacs som en bakgrunnsprosess
kommando | virkning |
---|---|
$ ps | Lister shellets prosesser |
$ ps aux (eller -Al) | Alle prosesser |
$ top | Dynamisk ps -aux |
$ kill 1872 | Drep prosess med PID 1872 |
$ kill -9 1872 | Forsert drap av 1872 |
$ time mittScript.bash | Måler tidsforbruket |
', `
og "
som alle
har forskjellig betydning:
$ dir=mappe $ echo 'ls $dir' ' -> Gir eksakt tekststreng ls $dir $ echo "ls $dir" " -> Variabler substitueres; verdien av $dir skrives ut. ls mappe $ echo `ls $dir` ` -> utfører kommando! fil1 fil2 fil.txt |
Huskeregel
' -> / -> Linux -> vet hva man får ` -> \ -> Windows -> aner ikke hva man får |
Et mer robust alternativ når en kommando skal utføres:
echo $(ls $dir) |
Dette gir også mer lesbar kode. I tillegg kan man ikke ha uttrykk med apostrofer inni hverandre:
rex$ line=`grep `whoami` /etc/passwd` Usage: grep [OPTION]... PATTERN [FILE]... Try 'grep --help' for more information. bash: /etc/passwd: Permission denied |
Men dette går fint med $()
syntaksen:
rex$ line=$(grep $(whoami) /etc/passwd) rex$ echo $line haugerud:x:5999:9002:Hårek Haugerud,,,:/home/haugerud:/bin/bash |
Så generelt anbefales det å bruke denne. Om man prøver følgende uttrykk med apostrofer inni hverandre:
haugerud@studssh:~/mappe$ var=`/bin/ls `pwd` ` |
Det vil si, det ga ingen feilmeldinger. Men om man ser nøyere på hva resultatet ble
haugerud@studssh:~/mappe$ echo $var fil.txtpwd haugerud@studssh:~/mappe$ pwd /iu/nexus/ua/haugerud/mappe haugerud@studssh:~/mappe$ ls fil.txt |
så ser vi at de ikke fungerte som ønsket. Igjen er det bedre å bruke $()
konstruksjonen:
haugerud@studssh:~/mappe$ var=$(/bin/ls $(pwd)) haugerud@studssh:~/mappe$ echo $var fil.txt |
$ mappe=`pwd` $echo $mappe /iu/nexus/ud/haugerud $ tall=`seq 5 10` $ echo $tall 5 6 7 8 9 10 |
Anbefalt alternativt:
$ mappe=$(pwd) $ tall=$(seq 5 10) $ echo $tall 5 6 7 8 9 10 $ tall=$(echo {5..10}) $ echo $tall 5 6 7 8 9 10 |
De fleste Linux programmer og kommandoer har alltid tre åpne kanaler:
nummer | navn | fullt navn | funksjon | default |
---|---|---|---|---|
0 | stdin | standard in | input kanal | fra tastatur |
1 | stdout | standard out | output kanal | til skjerm |
2 | stderr | standard error | kanal for feilmelding | til skjerm |
Dataene som strømmer inn og ut av disse kanalene (streams) kan omdirigeres til og fra filer og programmer.
$ echo hei hei $ echo hei > fil1 $ cat fil1 hei $ echo hei2 >> fil1 $ cat fil1 hei hei2 |
omdirigering | virkning |
---|---|
> fil.txt |
omdirigerer stdout til fil.txt. Overskriver |
>> fil.txt |
legger stdout etter siste linje i fil.txt |
>& fil.txt |
sender også stderr til fil.txt |
2> err.txt |
sender stderr til err.txt |
2> /dev/null |
stderr sendes til et 'sort hull' og forsvinner |
> fil.txt 2> err.txt |
stdout -> fil.txt stderr -> err.txt |
find / -name passwd 2>&1 | grep -v Permission |
sender stderr til samme kanal som stdout |
prog < fil.txt |
sender fil til stdin for program |
$ ehco hei ehco: Command not found $ ehco hei >& fil1 $ cat fil1 ehco: Command not found $ echo hei > fil1 2> err.txt # Sender error til err.txt $ mail haugerud < fil1 |
Konstruksjonen 2>&1
betyr: send stderr til samme kanal som stdout. Man limer da stderr-kanalen til
kommandoen på samme linje inn i stdout-kanalen. I eksempelet over vil det føre til at man kan grep'e på
både stdout og stdin fra find. Uten 2>&1
ville man bare kunne grep'e på stdout. Denne konstruksjonen kan også brukes som alternativ til >&
, kommandoen
ls /tmp/finnesikke > fil.txt 2&>1 |
vil sende stderr til fil.txt (men må stå etter >
).
Konstruksjonen 1>&2
betyr: send stdout til samme kanal som stderr. Inne i et script vil
echo "Error!" 1>&2 |
sende feilmeldinger til stderr, slik programmer vanligvis gjør. Vanligvis sender echo output til stdin,
men 1>&2
gjør at stdout istedet sendes til stderr.
$ ps aux > fil $ more fil |
Med pipe:
$ ps aux | more |
Dette gjør at man kan kombinere alle Linux-kommandoene på en rekke måter. Noen eksempler:
$ ps aux | grep haugerud | more $ cat /etc/passwd | sort > fil.txt $ sort /etc/passwd > fil.txt $ ps aux | awk '{print $1}' | sort | uniq | wc -l $ ps -eo user | sort | uniq | wc -l |
Forklaring til det siste eksempelet: ps -eo user
gir bare brukernavnet i ps-listingen. sort
sorterer listen med brukernavn alfabetisk. uniq
fjerner
identiske linjer, men kun de som kommer etter hverandre, derfor sort først.
wc -l
returnerer antall linjer. En slik
'pipeline' gir dermed antall brukere som kjører prosesser på maskinen.
|&
sender man også stderr videre:
$ ehco hei | grep found No command 'ehco' found, did you mean: Command 'echo' from package 'coreutils' (main) ehco: command not found $ ehco hei |& grep found No command 'ehco' found, did you mean: ehco: command not found |
Finnes det en annen måte å gjøre det samme på?
(kommando;kommando)
gir et såkalt subshell. Da startes et nytt shell og man mottar
den samlede output til stdout og stderr i shellet som kjører kommandoen. Det kan f.eks. brukes til å slå sammen
output fra to filer:
$ cat > fil1 en to tre $ cat > fil2 tre to fire $ sort fil2 fire to tre |
Hvis man ønsker å skrive ut de to filene med en kommando, kan man gjøre
$ cat fil2;cat fil1 tre to fire en to tre |
Men anta at man ønsker å sortere output fra de to filene; da kan man prøve følgende:
cat fil1;cat fil2 | sort en to tre fire to tre |
Men det som skjer er at bare fil2 blir sortert. Om man lager et sub-shell
$ (cat fil1;cat fil2) en to tre tre to fire |
vil output fra dette subshellet samlet sendes til sort:
$ (cat fil1;cat fil2) | sort en fire to to tre tre |
og man oppnår det man ønsket.
$ emacs change |
---|
#! /bin/bash |
cd /usr/bin |
pwd |
$ pwd / $ change /usr/bin $ pwd / |
Når scriptet change kjøres, starter en ny prosess; et nytt shell som utfører
cd /usr/bin |
og avsluttes. All shell-info blir da borte (variabler og posisjon i filtreet).
![]() |
Kommandoen source
utfører linje for linje i argumentfilen uten å starte noe annent shell.
$ pwd / $ source change /usr/bin $ pwd /usr/bin |
I Bash er .
og source
ekvivalent:
$ . change # samme som $ source change |