Lynkurs i shellprogrammering under Linux
Interaktiv bruk av shell Shell/skall er en applikasjon som lar bruker taste inn tekstlige kommandoer til Linux en og en linje om gangen (leser linjer fra stdin). Shellet sjekker om kommandoen som er gitt tilsvarer en Linux-kommando/et eksekverbart program på systemet, og starter i såfall dette. Kontrollen går tilbake til shellet etter endt programutførelse (evt. kan kommandoen kjøres i bakgrunnen), og neste kommando kan tastes. Finnes mange ulike shell, vi skal holde oss til Bourne (Again) shell.
Shellprogrammer Shellet kan lese kommandoer fra fil i stedet for tastaur, linje for linje inntil filen er slutt. Hver linje på filen interpreteres som en Linuxkommando og eksekveres på vanlig måte. Shellet tilbyr også kontrollstrukturer og variable, som i et vanlig programmeringsspråk. En fil med shellkommandoer og shellkode kalles for et shellprogram (eller shellscript). Shellprogrammering = «scripting»
Hello, world! #!/bin/sh echo "Hello, world!" exit 0
Kjøring av shellprogrammer Enten: chmod +x filnavn./filnavn Eller: sh filnavn
Variabler Variable i shell er uten type: Lagrer bytes Tolkes som enten tegn eller tall Trenger ikke deklareres, opprettes ved første referanse til variabelen: VAR=verdi For å bruke variabelen/se på verdien: $VAR eller ${VAR}
Tilordning og bruk av variabel #!/bin/sh FARGE=Rød echo $FARGE echo $FARGEaktig echo ${FARGE}aktig
Innlesning av verdier #!/bin/sh echo "Morn. Hva heter du?" read fornavn etternavn echo "Hyggelig å hilse på deg, $fornavn $etternavn"
Noen spesielle systemvariabler $0: Navnet på filen som inneholder programmet $1 $2 $3... $9: Argumentene på kommandolinjen (bruk shift hvis flere enn 9) $#: Antall argumenter på kommandolinjen $*: "$1 $2 $3... $#" $?: Exit status fra sist utførte kommando (et heltall, lik 0 null hvis «normal exit» Og mange fler...
Test av systemvariabler #!/bin/sh echo "Hei, jeg heter $0, og jeg har fått $# argumenter på kommandolinjen" echo "De tre første argumentene er: $1 $2 $3" echo "Her er alle argumentene: $*" # Kjører en lovlig kommando, "kaster" output who > /dev/null echo "Status: $?" # Prøver å kjøre en kommando som ikke finnes, "kaster" feilmeldingen dennekommandoenfinnesikke 2> /dev/null echo "Status: $?" exit 0
Noen spesialtegn i shellet < > : Redirigering av stdin og stdout *: Ekspanderes til en liste over alle filer i stående katalog?: Et hvilket som helst tegn [tegn]: Ett av tegnene inne i parantesene \: Ikke behandle neste tegn som spesialtegn 'foo': Alt mellom enkle anførselstegn siteres "foo": Bevarer space og «de fleste» spesialtegn, men ekspanderer variable og bakslasker `kommando`: kommandoen som står inne i «backquotes» utføres, verdien av uttrykket er utskriften fra kommandoen
Test av spesialtegn #!/bin/sh echo Alle filer i stående katalog: * echo Filer med navn som er på 5 tegn:????? echo Filer med navn som inneholder \"d\" eller \"o\": `ls *[od]*` echo 'Spesialtegn skrives rett ut mellom single quotes: *?"\`[]$0$$<> ' echo "Men ikke alltid mellom double quotes: *? $0<> \\\$0" antall_filer=`ls wc l` echo Antall filer: $antall_filer
Kontrollstrukturer i shell Seleksjon: if case Iterasjon: while for Og noen flere...
if-eksempel #!/bin/sh myname=`whoami` if [ $myname = janh ] then echo "Hællæ gamle ørn" else echo "Står De på gjestelisten?" exit 1 fi exit 0
if med flere grener #!/bin/sh echo "Morn. Har du det bra?" read svar if [ "$svar" = "ja" o "$svar" = "Ja" o "$svar" = "JA" ] then echo "Det var hyggelig" elif [ "$svar" = "nei" o "$svar" = "Nei" o "$svar" = "NEI" ] then else fi echo "Det var da trist" echo "Error 10: Too low user IQ"
if-syntaks if condition then commands [elif condition then commands] [else commands] fi
«Condition»/Logiske tester i shell Utføres av kommandoen test [uttrykk] er «syntaktisk sukker» for test test beregner logiske utrykk og returnerer 1 (true) eller 0 (false) To one-linere som er ekvivalent kode: if test Jan=Jan; then echo OK; fi if [ Jan=Jan ]; then echo OK; fi Kan også teste med andre kommandoer ($?): if who grep janh; then echo Hacker alert; fi
Noen logiske utrykk i shell -r filename Fil lesbar? -w filename Kan fil skrives? String Er streng ikke-tom? s1 = s2 Er strengene like? s1!= s2 Eller ikke-like? n1 -eq n2 Er tallene like? n1 -ne n2 Eller ikke-like? n1 -gt n2 Er tallet n1 størst? n1 -ge n2 Større eller lik? n1 -lt n2 Er n1 minst? n1 -le n2 Mindre eller lik?! expression Negasjon expr1 -a expr2 Logisk AND expr1 -o expr2 Logisk OR ( expression ) Gruppering med paranteser
case $# in 0) echo -n "Filnavn? "; read filnavn ;; 1) filnavn=$1 ;; *) echo usage: $0 [file] exit 1 ;; esac if [! -f $filnavn ] then echo $0: $filnavn is not a valid file; exit 1 fi echo Congratulations, you entered a valid file name! case-eksempel
for og while for var in list do commands done while condition do commands done for-løkke går gjennom en space-separert liste av verdier while-løkke krever ofte tallregning i shell, gjøres med expr (eller raskere med let, aka (( )) Løkker kan kontrolleres med break (hopp ut av løkken) eller continue (gå til neste iterasjon)
for-eksempel for i in foo bar baz "do be do" do echo "$i" done
Telle antall filer i stående katalog n_files=0 for file in `ls` do n_files=$((n_files+1)) done echo $n_files
Samsortere første linje på alle tekstfiler i stående katalog for file in *.txt do head 1 $file done sort o sorted_headers
#!/bin/sh # Sorterer alle de lesbare filene i angitte kataloger if [ $# -lt 1 ] then echo usage: $0 directory1 [directory2 directory3...] exit 1 fi for dir in $* do if [! -d $dir ] then echo $0: $dir is not a valid directory exit 1 fi cd $dir for file in * do if [ -r $file ] then sort -o ${file}_sorted $file fi done cd.. done
While-eksempel: Sum av naturlige tall #!/bin/sh i=0 sum=0 while [ $i lt $1 ] do i=`expr $i + 1` sum=`expr $sum + $i` done echo 1+2+3+...+$1 = $sum exit 0
Hacker-detektoren #!/bin/sh # Slår alarm når hackeren logger seg på while!(who grep beathedue > /dev/null) do sleep 30 done echo `date`: Hacker alert!
Det plagsomme scriptet #! /bin/sh # Test av trap trap "echo 'He he, det hjelper ikke med ^C...'" 2 while [ 1 ] do echo "Jeg er shellscriptet som skal plage deg til evig tid >: )" done sleep 3
Behandle en fil en linje om gangen #!/bin/sh # Behandler en fil en linje om gangen. # Skriver ut linjene nummerert line_no=0 cat $1 \ while read line do line_no=`expr $line_no + 1` echo $line_no: $line done