Difference between revisions of "Bash"

From Teknologisk videncenter
Jump to: navigation, search
m (Beregninger i scripts)
m (Debugging scripts)
 
(16 intermediate revisions by 2 users not shown)
Line 2: Line 2:
  
 
Bash kaldes ofte i engelsk litteratur for en CLI - Command Line Interpreter eller kommandofortolker på dansk.
 
Bash kaldes ofte i engelsk litteratur for en CLI - Command Line Interpreter eller kommandofortolker på dansk.
 +
 +
 +
Der findes flere artikler om [[bash]] indelt efter emner:
 +
*[[Bash processer]] - Processer, omdirigeringer, Pipe tegnet
 +
*[[Bash scripts]] - Om at lave bash scripts (while, if, do, test)
 +
*[[Bash scripts II]] Mere avancerede funktioner
 +
*[[Bash examples]] - forskellige bash shell script eksempler
 +
*[[UNIX commands|UNIX/Linux Commands]]
  
 
= Filer =
 
= Filer =
Line 43: Line 51:
 
**Brug enten '''set +x''' eller '''set +o xtrace''' for at de-aktivere trace mode
 
**Brug enten '''set +x''' eller '''set +o xtrace''' for at de-aktivere trace mode
  
<pre class=pre>
+
<source lang=bash>
#!/usr/bin/bash
+
#!/bin/bash
 
#Kode her er OK
 
#Kode her er OK
 
...
 
...
Line 53: Line 61:
 
#kode her er ok
 
#kode her er ok
 
...
 
...
</pre>
+
</source>
 +
===En anden måde at debugge scripts i bash===
 +
<source lang=bash>
 +
#!/bin/bash
  
= Variable =
+
trap '(read -p "[$BASH_SOURCE:$LINENO] $BASH_COMMAND?")' DEBUG
Der er
 
== Beregninger i scripts ==
 
Følgende eksempel viser hvor meget performance der kan vindes ved at anvende den indbyggede funktion ''let'' i '''bash''' i stedet for at anvende det separate program ''expr''. Grunden til at det tager så lang tid at anvende ''expr'' er at '''bash''' skal starte en ny process hvergang '''expr''' udføres. (100.000 gange ialt)
 
<source lang=cli>
 
[heth@mars ~]$ <input>cat test-let-expr</input>
 
#!/usr/bin/bash
 
  
echo "#################### using let ####################"
+
A=1
A=0
+
while [ $A -lt 10 ]
TIMESTART=$(date +%s)
 
while test $A -lt 100000
 
 
do
 
do
let A=A+1
+
        let A=A+1
 +
        echo -n "A = $A\n"
 
done
 
done
let TIME=`date +%s`-TIMESTART
 
echo "It took $TIME seconds for let to count to $A"
 
 
echo "#################### using expr ###################"
 
A=0
 
TIMESTART=$(date +%s)
 
while test $A -lt 100000
 
do
 
A=`expr $A + 1`
 
done
 
let TIME=`date +%s`-TIMESTART
 
echo "It took $TIME seconds for expr to count to $A"
 
[heth@mars ~]$ <input>./test-let-expr</input>
 
#################### using let ####################
 
It took <notice>4</notice> seconds for let to count to 100000
 
#################### using expr ###################
 
It took <notice>250</notice> seconds for expr to count to 100000
 
 
</source>
 
</source>
'''''BEMÆRK:''''' I eksemplet ovenfor at ''VARIABEL=$(kommando)'' er det samme som ''VARIABEL=`kommando`''
 
  
= Job kontrol =
+
= Variable =
Job kontrol kan anvendes til at styre flere kørende programmer samtifig. Et kørende program kan suspenderes - dvs. stoppes - og resume - dvs. fortsætte - på et senere tidspunkt. Jobs kan køre i baggrunden - det vil sige ikke med standard output på skærmen.
+
Der er
{|border=1 ;style="margin: 0 auto; text-align: center;cellpadding="5" cellspacing="0"
+
== Arrays ==
|- bgcolor=lightgrey
+
Bash understøtter primitive Arrays.
! Funktion !! kommando
 
|-
 
| Stoppe kørende program i forgrunden || <CTRL>-Z
 
|-
 
| Se stoppede programmer og jobnumre|| jobs
 
|-
 
|Forsætte stoppet program i forgrunden || fg [job-nummer]
 
|-
 
|Fortsætte stoppet program i baggrunden || bg [job-nummer ...]
 
|}
 
= bash og processer =
 
Processer er de programmer der kører på maskinen og programmer du starter i '''bash'''.
 
== Fødslen af et process ==
 
Når der startes en ny process vil '''bash''' starte processen med tre åbne filhåndtag. Dette er den normale situation og sker hver gang der startes et program/process.
 
 
 
{|border=1 ;style="margin: 0 auto; text-align: center;cellpadding="5" cellspacing="0"
 
|- bgcolor=lightgrey
 
! Navn  !! filhåndtag # !! Forklaring
 
|-
 
|valign="top"|STDIN (Standard input) ||valign=top align="center"| 0 || Standard indlæsning af data. Hentes som standard fra tastaturet
 
|-
 
|valign="top"|STDOUT (Standard output) ||valign=top align="center"| 1 || Standard udlæsning af data. Sendes som standard til skærmen
 
|-
 
|valign="top"|STDERR (Standard error) ||valign=top align="center"| 2 || Fejl beskeder fra processem. Sendes som standard til skærmen
 
|-
 
|colspan=3|[[Image:Bash process 1.png|thumb|500px|center|En processes standard input/output. Der kan tastes på tastaturet til processen for eksempel vi editoren og tekst og fejlbeskeder vises på skærmen]]
 
|-
 
|}
 
I eksemplet herunder startes programmet '''grep''' af '''bash'' som en process med STDIN,STDOUT og STDERR. STDIN og STDERR anvendes ikke i eksemplet. men de er der.
 
<source lang="cli">
 
[heth@mars ~]$ <input>grep heth /etc/passwd</input>
 
heth:*:1001:1001:Henrik Thomsen:/home/heth:/usr/local/bin/bash
 
</source>
 
I eksemplet herunder - hvor der ikke angives et filnavn - vil '''grep''' anvende STDIN til at hente data som tastet på tastaturer. Linier med hvidt skrives og linier med grønt skriver '''bash''' linier med blå skriver '''grep'''
 
 
<source lang=cli>
 
<source lang=cli>
[heth@mars ~]$ <input>grep bil</input>
+
[heth@mars ~]$ <input>MYARRAY=(Banan Agurk Gulerod Radisse Kartoffel)</input>
<input>Jeg har en cykel</input>
+
[heth@mars ~]$ <input>echo -e "En ${MYARRAY[3]} smager godt"</input>
<input>maden er billig</input>
+
En Radisse smager godt
<notice>maden er billig</notice>
+
[heth@mars ~]$ <input>echo -e ${MYARRAY[*]}</input>
<input>der er to piller i skabet</input>
+
Banan Agurk Gulerod Radisse Kartoffel
<input>min bil skal til syn</input>
+
[heth@mars ~]$ <input>MYARRAY[3]=Citron</input>
<notice>min bil skal til syn</notice>
+
[heth@mars ~]$ <input>echo -e "En ${MYARRAY[3]} smager godt"</input>
<input>^C</input>
+
En Citron smager godt
[heth@mars ~]$  
+
[heth@mars ~]$ <input>echo -e ${MYARRAY[*]}</input>
 +
Banan Agurk Gulerod Citron Kartoffel
 +
[heth@mars ~]$ <input>echo -e "Der er ${#MYARRAY[*]} elementer i arrayet "</input>
 +
Der er 6 elementer i arrayet
 +
[heth@mars ~]$ <input>echo -e "Element 1 fylder ${#MYARRAY[1]} tegn"</input>
 +
Element 1 fylder 5 tegn
 +
[heth@mars ~]$ <input>echo -e "${MYARRAY[*]}"</input>
 +
Banan Agurk Gulerod Citron Kartoffel
 +
[heth@mars ~]$ <input>unset MYARRAY[1]</input>
 +
[heth@mars ~]$ <input>echo -e "${MYARRAY[*]}"</input>
 +
Banan Gulerod Citron Kartoffel
 
</source>
 
</source>
  
== Omdirigering af standard datastrømme ==
 
{|border=1 ;style="margin: 0 auto; text-align: center;cellpadding="5" cellspacing="0"
 
|- bgcolor=lightgrey
 
! Tegn !! Omdirigerer !! Eksempel !! Kommentar
 
|-
 
| > || STDOUT || grep Error /var/log/stor_logfil > /tmp/found_errors || Overskriver eventuelt eksisterende fil
 
|-
 
| >> || STDOUT || grep Error /var/log/stor_logfil >> /tmp/found_errors || Appender dvs. tilføjer til eventuelt eksisterende fil
 
|-
 
|2> || STDERR || backup /home 2> /tmp/backup_errors || Overskriver eventuelt eksisterende fil
 
|-
 
|2>> || STDERR || backup /home 2>> /tmp/backup_errors || Appender dvs. tilføjer til eventuelt eksisterende fil
 
|-
 
| < || STDIN || bc < /tmp/stort_regnestykke || Filen læses linie for linie ind i STDIN
 
|-
 
|2>&1 || STDOUT og STDERR || backup /home > /tmp/backup_log 2>&1 || STDERR filhåndtag 2 omdirigeres samme sted som filhåndtag 1
 
|}
 
=== Omdirigering af STDOUT ===
 
Som standard sendes STDOUT data fra processen til den aktive skærm. Det er muligt at omdirigere datastrømmen fra processens STDOUT til en fil ved at benytte omdirigeringstegnet '''>'''
 
{|
 
|[[Image:Bash process omdiriger STDOUT.png|500px|thumb|left|Omdirigering af STDOUT]]
 
|}
 
<source lang=cli>
 
[heth@mars ~]$ <input>grep error /var/log/stor_logfil > /tmp/errors</input>
 
[heth@mars ~]$ <input>cat /tmp/errors</input>
 
Aug 19 08:16:53 mars sshd[7359]: error: ssh_msg_send: write
 
Aug 19 09:12:32 mars sshd[7852]: error: ssh_msg_send: write
 
Aug 19 18:16:18 mars sshd[12351]: error: ssh_msg_send: write
 
Aug 20 03:04:16 mars sshd[13155]: error: ssh_msg_send: write
 
Aug 19 07:21:47 mars sshd[14256]: error: ssh_msg_send: write
 
</source>
 
=== Omdirigering af STDERR ===
 
Som standard sendes STDERR data fra processen til den aktive skærm. Det er muligt at omdirigere datastrømmen fra processens STDERR til en fil ved at benytte omdirigeringstegnet '''2>'''.
 
{|
 
|[[Image:Bash process omdiriger STDERR.png|500px|thumb|left|Omdirigering af STDERR]]
 
|}
 
Denne funktion kan for eksempel anvendes ved ikke øvervåget sikkerhedskopiering for at opsamle alle fejlbeskeder til senere analyse. Ellers ville beskederne bare rulle ovenud på skærmen.
 
<source lang=cli>
 
[heth@mars ~]$ <input>date</input>
 
Fri Aug 21 15:26:47 CEST 2009
 
[heth@mars ~]$ <input>backup /home 2>/tmp/backup_log_Aug22</input>
 
Backing up /home/.snap
 
Backing up /home/heth
 
Backing up /home/heth/.cshrc
 
Backing up /home/heth/.login
 
Backing up /home/heth/.login_conf
 
Backing up /home/heth/.mailrc
 
Backing up /home/heth/.profile
 
<notice> Tusinder af linier her </notice>
 
</source>
 
Check af om backupen gik godt
 
<source lang=cli>
 
[heth@mars ~]$ <input>date</input>
 
Mon Aug 24 08:01:47 CEST 2009
 
[heth@mars ~]$ <input>cat /tmp/backup_log_Aug22</input>
 
File busy: /home/hdje/doc/letter3.doc
 
</source>
 
=== Omdirigering af STDIN ===
 
Som standard modtager STDIN data fra tastaturet. Det er muligt at omdirigere datastrømmen fra tastaturet til en fil ved at benytte omdirigeringstegnet '''<'''.
 
{|
 
|[[Image:Bash process omdiriger STDIN.png|500px|thumb|left|Omdirigering af STDIN]]
 
|}
 
Hvis der for eksempel ønskes periodisk sikkerhedskopiering af de 127 vigtigste filer og biblioteker på maskinen, laves en fil med en liste over de vigtige filer. En pr linie.
 
<source lang=cli>
 
[heth@mars ~]$ <input>backup < /etc/vigtige_filer_liste </input>
 
Backing up /var/database/kunder
 
Backing up /var/database/leverandorer
 
Backing up /var/database/okonomi
 
Backing up /home/hejhr/projekt
 
<notice> Mange linier her</notice>
 
</source>
 
=== Flere omdirigeringer samtidig ===
 
der er muligt at kombinere omdirigeringer.
 
<source lang=cli>
 
[heth@mars ~]$ <input>backup < /etc/vigtige_filer 2>> /tmp/backup_errors 1>> /tmp/backup_files </input>
 
</source>
 
== Pipes - sammenkobling af processer ==
 
Ved at anvende pipe-symbolet '''|''' kan STDOUT fra en process ''pipes'' til STDIN på en anden process. Se principtegning og ekesempel herunder. STDERR fra begge processer sendes til skærmen.
 
{|
 
|[[Image:Bash process pipe princip.png|700px|thumb|left|STDOUT fra process 1 pipes til STDIN på process 2. STDERR fra begge processer sendes til skærmen.]]
 
|}
 
I eksemplet herunder vil kommandoen '''find /home -ctime -24h''' finde alle filer under biblioteket /home som er ændret inden for de sidste 24 timer, og skrive deres tilnavne ud på STDOUT. STDOUT er imidlertidigt pipet til backup kommandoen som tager tager backup af de filer den modtager via STDIN.
 
<source lang=cli>
 
[heth@mars ~]$ <input>find /home -ctime -24h | backup</input>
 
</source>
 
  
{{#css:
+
 
   
+
{{Source cli}}
    pre {  font-family: Lucida Console; font-weight: bold; font-size: 14px; color: #00FF00; background: black; margin: 10px 50px; width: 800px; line-height: 200%; overflow: auto;}
 
}}
 
  
 
= Eksterne henvisninger =
 
= Eksterne henvisninger =
Line 236: Line 111:
 
*[http://www.tldp.org/LDP/Bash-Beginners-Guide/Bash-Beginners-Guide.pdf Bash Beginners Guide]
 
*[http://www.tldp.org/LDP/Bash-Beginners-Guide/Bash-Beginners-Guide.pdf Bash Beginners Guide]
 
*[http://www.tldp.org/LDP/abs/abs-guide.pdf Advanced Bash-Scripting Guide]
 
*[http://www.tldp.org/LDP/abs/abs-guide.pdf Advanced Bash-Scripting Guide]
[[Category:Linux]][[Category:Bash]][[Category:UNIX]]
+
*[http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html Bash programming HOWTO Intro]
 +
[[Category:Linux]][[Category:Bash]][[Category:UNIX]][[Category:Linux Command]]

Latest revision as of 12:38, 21 November 2020

bash - eller Bourne Again Shell - er den mest benyttede shell eller kommandofortolker til Unix og Linux systemer i dag. Der findes andre shells end bash. For eksempel csh (C-Shell), ksh (Korn-Shell) og bsh (Bourne-Shell).

Bash kaldes ofte i engelsk litteratur for en CLI - Command Line Interpreter eller kommandofortolker på dansk.


Der findes flere artikler om bash indelt efter emner:

Filer

Selve programmet bash kan være installeret i forskellige biblioteker på forskellige systemer men findes oftest i /usr/bin biblioteket. På BSD Unix varianter findes bash ofte i /usr/local/bin. Hvis du ikke ved hvor din lokale bash findes kan den findes med whereis bash kommandoen.


/etc/profile Opstartsfil som bash udfører for alle brugere på maskinen. Udføres før den personlige opstartsfil.
$HOME/.bash_profile Denne fil er din personlige opstartsfil og vil blive udført når du logger ind på systemet, og indeholder typisk opstartskommandoer, velkomst... Hvis .bash_profile ikke eksister i dit hjemmebibliotek vil bash kigge efter filen .bash_login og udføre den. Hvis denne heller ikke eksister kigger bash efter filen .profile og udfører kommandoerne i den. Bemærk kun en af disse filer vil blive udført i rækkefølgen: 1: .bash_profile 2: .bash_login eller 3: .profile
$HOME/.bashrc Denne fil er personlig og vil blive udført hvergang der startes en sub-shell, det vil sige hvergang bash starter en ny

bash

$HOME/.bash_logout Denne fil er din personlig afslutningsfil og udføres når der logges ud.
$HOME/.inputrc Denne fil indeholder opstartskommandoer til bash. Anvendes til for eksempel at ændre tastatur genveje.

Online bash hjælp

  • On line manualen: man bash
  • indbygget bash hjælp: help
  • hjælp til bash indbyggede kommandoer: help while (eksempel)

bash tilpasning med set kommandoen

Hvis du ønsker at ændre bash måde at fungere på kan set kommandoen anvendes. Dette er normalt ikke nødvendigt.

  • Kommandoer
    • help set

Debugging scripts

Det kan være svært at debugge scripts og se hvor problemet er. Her kan bash sættes i enten verbose eller trace mode. Verbose eller trace mode kan slås til og fra efter behag i dit script.

  • verbose mode. (Viser kommandoer som de læses fra scriptet. Som de er skrevet)
    • Brug enten set -v eller set -o verbose for at aktivere verbose mode
    • Brug enten set +v eller set +o verbose for at de-aktivere verbose mode
  • trace mode. (Viser kommandoer som de udføres i scriptet. Fx. indholdet af variablerne.
    • Brug enten set -x eller set -o xtrace for at aktivere trace mode
    • Brug enten set +x eller set +o xtrace for at de-aktivere trace mode
#!/bin/bash
#Kode her er OK
...
set -x    #bash trace mode slået til og alle kommandoer udført vises på skærmen
#mistænkelig kode her
...
set +x   #bash trace mode slået fra og bash fungerer normalt
#kode her er ok
...

En anden måde at debugge scripts i bash

#!/bin/bash

trap '(read -p "[$BASH_SOURCE:$LINENO] $BASH_COMMAND?")' DEBUG

A=1
while [ $A -lt 10 ]
do
        let A=A+1
        echo -n "A = $A\n"
done

Variable

Der er

Arrays

Bash understøtter primitive Arrays.

[heth@mars ~]$ <input>MYARRAY=(Banan Agurk Gulerod Radisse Kartoffel)</input>
[heth@mars ~]$ <input>echo -e "En ${MYARRAY[3]} smager godt"</input>
En Radisse smager godt
[heth@mars ~]$ <input>echo -e ${MYARRAY[*]}</input>
Banan Agurk Gulerod Radisse Kartoffel
[heth@mars ~]$ <input>MYARRAY[3]=Citron</input>
[heth@mars ~]$ <input>echo -e "En ${MYARRAY[3]} smager godt"</input>
En Citron smager godt
[heth@mars ~]$ <input>echo -e ${MYARRAY[*]}</input>
Banan Agurk Gulerod Citron Kartoffel
[heth@mars ~]$ <input>echo -e "Der er ${#MYARRAY[*]} elementer i arrayet "</input>
Der er 6 elementer i arrayet
[heth@mars ~]$ <input>echo -e "Element 1 fylder ${#MYARRAY[1]} tegn"</input>
Element 1 fylder 5 tegn
[heth@mars ~]$ <input>echo -e "${MYARRAY[*]}"</input>
Banan Agurk Gulerod Citron Kartoffel
[heth@mars ~]$ <input>unset MYARRAY[1]</input>
[heth@mars ~]$ <input>echo -e "${MYARRAY[*]}"</input>
Banan Gulerod Citron Kartoffel



Eksterne henvisninger