Bash Programmierung: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
Link auf Zeiten I. umgestellt
 
(57 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
=Bash Basics=
=Allgemeines=
*[[Einfache Shellsonderzeichen]]
*[[Thomas Will]]
*[[Bash Eingabe/Ausgabe]]
*[[Zeiten I.]]
*[[Jokerzeichen]]
=Themen=
*[[Prinzip der Bash]]
*[[Bash Programmierung Inhalt]]
*[[Interpretator]]
<!-- == Tag 1 ==  -->
*[[Ablauf eines Shell-Skriptes]]
* [[Die Geschichte der Shells]]
*[[Möglichkeiten ein Shellskript aufzurufen]]
* [[Ziele des IT Trainings Bash Programmierung]]
*[[Bash Variablen]]
* [[Arten von Shells]]
*[[Bash Dateien]]
* [[Prinzip der Bash]]
*[[Here Dokument]]
* [[Unterschiede zwischen bash und powershell]]
*[[read-Kommando]]
* [[Skript Interpreten in Linux]]
*[[Einfache Verzweigungen]]
* [[Möglichkeiten ein Shellskript aufzurufen]]
*[[Endestatus]]
* [[Bash Eingabe, Ausgabe und Pipes]]
*[[test-Kommando]]
* [[Einfache Shellsonderzeichen]]
*[[Optionen der Bash]]
* [[Jokerzeichen/Wildcard]]
*[[Bash Der if-Block]]
* [[Ein paar Kommandos]]
*[[Bash Der case-Block]]
* [[Kommandolokalisierung]]
*[[Rechnen mit der Bash]]
* [[Bash ssh in Programmen nutzen]]
*[[Bash Die while-Schleife]]
<!-- == Tag 2 == -->
*[[Bash Die until-Schleife]]
* [[Ablauf eines Shell-Skriptes]]
* [[Bash Variablen]]
* [[Bash Dateien]]
* [[Here Dokument]]
* [[Here String]]
* [[read-Kommando]]
* [[Endestatus]]
* [[Bash Einfache Verzweigungen]]
* [[test-Kommando]]
* [[Bash Das neue Test Kommando]]
* [[Rechnen mit der Bash]]
<!-- == Tag 3 == -->
<!-- == Tag 4 == -->
* [[Bash Der if-Block]]
* [[Bash Der case-Block]]
* [[Bash Die while-Schleife]]
* [[Bash Die until-Schleife]]
* [[Bash Die for-Schleife]]
* [[Bash Steuerung der Ablaufanweisungen]]
* [[Bash funktion]]
* [[cron]]
* [[Bash Signalverarbeitung]]
<!-- == Tag 5 == -->
* [[Bash printf]]
* [[Aliase]]
* [[Prozesse]]
* [[Bash Filedeskriptoren]]
* [[Bash Farben]]
* [[Bash getopts]]
* [[Bash eval]]
* [[Optionen der Bash]]
* [[Bit Operationen mit der Bash]]
* [[Bash Skripte]]
* [[Mail Kommando]]
* [[Bash Passwort generieren]]
* [[Bash Alter eine Datei]]
* [[Ssh VPN]]
* [[Aufgaben gesamt]]


*[[Bash Die for-Schleife]]
= Links=
 
* http://openbook.rheinwerk-verlag.de/shell_programmierung/
*[[Bash Steuerung der Ablaufanweisungen]]
* http://mywiki.wooledge.org/BashFAQ/031
 
* http://tldp.org/LDP/abs/html/index.html
*[[bash funktion]]
* http://openbook.rheinwerk-verlag.de/shell_programmierung/shell_006_003.htm
 
* https://kuepper.userweb.mwn.de/informatik/printf.pdf
=Signalbehandlung=
==Signale bei der Programmierung der bash==
Es existieren verschiedene Möglichkeiten, auf welchem Wege Signale gesendet werden können:
 
# von aussen:
## Benutzer (< DEL >, < CTRL >|, etc.)
## Prozesse (kill, alarm)
# von innen:
## Programmfehler (Adressfehler, ungültiger Befehl, Division durch 0, etc.)
 
Signale dienen der Interprozesskommunikation. Diese Nachrichten beschränken sich allerdings auf die Übertragung eines einzigen Wertes.
Von den Befehlen ''trap'' und ''kill'' werden folgende Signale verwendet:
 
{| border="1" cellpadding="2"
! Signalnummer
! Bedeutung
|-
| 0
| Beenden von bash
|-
| SIGHUP 1
| Logoff von einer Datensichtstation
|-
| SIGINT 2
| Drücken der Taste < DEL >
|-
| SIGQUIT 3
| Drücken der Taste < CTRL > + c
|-
| SIGKILL 9
| kill: unbedingter Prozessabbruch
|-
| SIGTERM 15
| Programmbeendigung
|}
 
==Reaktion eines Prozesses auf den Empfang eines Signals==
* Der Prozess beendet sich (meist Standardeinstellung).
* Der Prozess ignoriert das Signal. (Ausnahme: SIGKILL)
* Der Prozess fängt das Signal ab, d.h. er leitet eine selbst definierte Reaktion ein.
 
=Der Befehl trap =
'''Funktionen:'''
 
;Signalbehandlung setzen
(Nach Beendigung der bash werden die betreffenden temporären Dateien gelöscht)
*trap 'rm *.tmp' 0
*trap 'who; exit 1' 2 3
;Liefern von Informationen über gesetzte Signalbehandlung
*trap
 
;Zurücksetzen der Signalbehandlung
*trap 2 3
 
;Import von Signalen
*trap : 2 3
*trap '' 2 3
 
;Demonstriert die Funktion trap zum Abfangen von Signalen
<syntaxhighlight>
#!/bin/bash
trap 'echo trap ausgelöst' 2
i=0
while [ $i -lt 5 ]
do
  echo "Bitte nicht stören!"
  sleep 2
  i=`expr $i + 1`
done
</syntaxhighlight>
Bemerkung: Die Signalbehandlung selbst wird nicht an Kindprozesse weitervererbt. Das Ignorieren von Signalen hingegen wird weitervererbt.
 
=Weitere Möglichkeiten der Bash-Shell=
==Alias-Namen==
*[[aliase]]
 
=Filedeskriptoren=
==Schreibenden Deskriptor==
;anlegen
*exec 5> /tmp/five
;rein schreiben
*echo eins >&5
*echo zwei >&5
*echo drei >&5
;ausgeben
*cat /tmp/five
;aufheben
*exec 5>&-
;führt zu Fehler
*echo vier >&5
==Lesender Deskriptor==
;anlegen
*exec 7< /etc/hosts
;auslesen
*cat <&7
;geht nur einmal
*cat <&7
 
==Gleichzeitiges Lesen aus verschiedenen Dateien==
<syntaxhighlight>
#!/bin/bash
exec 3< /etc/passwd
exec 4< /etc/shadow
while true
do
  read var3 <&3
  read var4  <&4
  echo passwd  $var3
  echo shadow $var4 ;
  test -z $var4 && break
done
</syntaxhighlight>
==Gleichzeitiges Lesen aus Datei und Standardeingabe==
<syntaxhighlight>
#!/bin/bash
exec 3< $1
while read line <&3
do
  echo $line
  printf "Eine weitere Zeile einlesen? [j/n] : "
  read REPLY
  test "$REPLY" = "n"  && break
done
</syntaxhighlight>
 
=Bearbeiten von Farben=
 
Um die Farben in der Shell zu ändern, müssen wir bestimmte Zeichenfolgen senden. Die Zeichenkette \033\13301;31m würde z.B. alles Weitere in Rot ausgeben.
 
Format: \033\133;m
 
Diese Methode kann allerdings beim Setzen der Variable $PS1, die den Prompt kontrolliert, dazu führen, dass der Zeilenumbruch falsch berechnet wird. Deshalb ist in diesem Fall der Einschluss in \[ \] erforderlich.
 
Format: \[\033\133;m\]
 
Um mit dem Farbigen aufzuhören und wieder normal zu schreiben sendet man einfach folgende Zeichenfolge:
 
\033\1330m
 
Textdekorationen:
00 - Schmaldruck
01 - Keine
02 - dunkle Version der Farbe
04 - Unterstreichen
05 - Invertieren
 
Farben:
30 - Schwarz
31 - Rot
32 - Grün
33 - Gelb
34 - Blau
35 - Lila
36 - Cyan
37 - Grau
 
Hintergründe färben:
40 - Schwarz
41 - Rot
42 - Grün
43 - Gelb
44 - Blau
45 - Lila
46 - Cyan
47 - Grau
 
Austesten wie es dann genau aussieht kann man das mit den folgenden Befehlen:
 
for i in `seq 40 47`;do echo -e "Farbnummer:\033\13301;"$i"m $i \033\01330m";done
for i in `seq 30 37`;do echo -e "Farbnummer:\033\13301;"$i"m $i \033\01330m";done
 
=getopts=
<syntaxhighlight>
#!/bin/bash
function examine()
{
FILE=$1
shift
echo "Rights on $FILE"
for k in $*
do
case $k in
u) echo USER : $(ls -l $FILE | cut -c 1-3) ;;
g) echo GROUP: $(ls -l $FILE | cut -c 4-6) ;;
o) echo OTHER: $(ls -l $FILE | cut -c 7-9) ;;
esac
done
}
while getopts ugof: opt
do
  case $opt in
      u) OPT="${OPT} u";;
      g) OPT="${OPT} g";;
      o) OPT="${OPT} o";;
      f) DAT=$OPTARG;;
      ?) echo "USAGE: $0 -ugo -f FILE"; exit 2 ;;
  esac
done
examine $DAT $OPT
</syntaxhighlight>
;Erklärung
*Das Program kann mit den Optionen -u -g -o und -f Datei aufgerufen werden.
*Die Optionen ugo werden in der Variable $OPT "gesammelt".
*Alle Optionen werden an die Funktion examine übergeben.
*Die Optionen werden oben getrennt und je nach vorhandener Option werden Anweisungen ausgeführt.
 
 
*http://openbook.galileocomputing.de/shell_programmierung/shell_005_007.htm
 
=printf=
Formatierte Ausgabe mit printf
 
Im einfachsten Fall wird ein fester Text auf dem Bildschirm ausgegeben:
*printf("Dies ist ein einfaches Beispiel");
Der Text kann auch Sonderzeichen (z. B. Zeilenumbrüche) enthalten:
*printf("Hier werden \n zwei Zeilen ausgegeben!");
Die Zeichensequenz \n bewirkt einen Sprung an den Anfang der folgenden Bildschirmzeile. Weitere gebräuchliche Sonderzeichen sind:
{| class="wikitable"
|-
|\n
|Sprung an den Anfang der folgenden Bildschirmzeile
|-
|\b
|Gehe ein Zeichen zurück
|-
|\a
|Akustisches Signal
|-
|\r
|Sprung an den Anfang der aktuellen Bildschirmzeile
|-
|\\
|Ausgabe des Gegenschrägstrichs "\" (Backslash)
|-
|%%
|Ausgabe des Prozent-Zeichens "%"
|-
|\"
|Ausgabe eines doppelten Anführungszeichens
|-
|\t
|Sprung zur nächsten Tabulatorposition
|}
Sollen aktuelle Variablenwerte ausgegeben werden, werden in den Aufruf der
 
Funktion printf entsprechende „Platzhalter“ eingefügt:
*int x = 10;
*printf("Der Wert %d wurde der Variablen x zugewiesen.", x);
Auf dem Bildschirm erfolgt die Ausgabe „Der Wert 10 wurde der Variablen x zugewiesen“, es wird also der Platzhalter %d durch den aktuellen Wert der Variablen x
ersetzt. Es ist möglich, mehrere Variablen zugleich auszugeben:
*int x = 123, y = 234;
*printf("x = %d und y = %d", x, y);
Die Ausgabe lautet in diesem Fall „x = 123 und y = 234“. Für jede Variable ist ein
eigener Platzhalter (hier: %d) notwendig. Die auszugebenden Variablen werden
durch Kommas getrennt aufgelistet. Für jeden Platzhalter muss dabei eine Variable angegeben werden (hier: x, y).
Es ist zu beachten, dass der Platzhalter zum Typ der auszugebenden Variablen
passt (z. B. dient %d zur Ausgabe einer Variablen des Typs int, short oder long).
Weitere Platzhalter sind:
 
{| class="wikitable"
|-
|%d, %i
|int, short, long
|Ganze Zahl
|-
|%x, %X
|int, short, long
|Ganze Zahl, Ausgabe als Hexadezimalzahl
|-
|%f
|float, double
|Fließkommazahl
|-
|%e, %E
|float, double
|Fließkommazahl, Ausgabe im Exponentialformat
|-
|%c
|char
|Einzelnes Zeichen (Buchstabe, Ziffer, …)
|-
|%s
|char*
|Zeichenkette („String“)
|}
;Beispiel:
*int i = 10; double d = 22.22; char c = 'X';
*char* str = "abcdefg...";
*printf("Beispiel zu printf:\n");
*printf("%d, %f, %c\n", i, d, c);
*printf("%s", str);
Es kann die Breite des Ausgabebereichs angegeben werden. So wird mit %10d
eine ganze Zahl rechtsbündig in einem Bereich von 10 Zeichen Länge ausgegeben:
int i = 123;
*printf("->%d<-\n", i);
*printf("->%4d<-\n", i);
*printf("->%5d<-\n", i);
Bei der Ausgabe von Fließkommazahlen kann zusätzlich zur Länge des Ausgabebereichs die Anzahl der Nachkommastellen eingestellt werden:
*float f = 123.625;
*printf("->%f<-\n", f);
*printf("->%.2f<-\n", f);
*printf("->%10.0f<-\n", f);
*printf("->%10.1f<-\n", f);
*printf("->%10.2f<-\n", f);
*printf("->%10.3f<-\n", f);
*printf("->%10.4f<-\n", f)
==Beispielskript==
<syntaxhighlight>
#!/bin/bash
for DIR in $(df -t ext4  | awk 'NR>1 {  print $6 }')
do
  PROZENT=$(df -t ext4 $DIR | awk 'NR>1 {  print $5 }')
  PRO=$(echo $PROZENT | tr -d "%")
  let KI=PRO*20/100
  let MI=20-KI
    K="####################"
    M='--------------------'
  printf "%-10s%-4s%.${KI}s%.${MI}s" $DIR $PROZENT $K $M
    echo
done
</syntaxhighlight>
==Links==
*https://linuxconfig.org/bash-printf-syntax-basics-with-examples
 
=Das neue Test Kommando=
*"[[" ist Bashs Verbesserung des "[" Befehls.
*Es ist die bessere  Wahl, wenn Sie Skripte schreiben, die auf Bash abzielen. Meine Favoriten sind:
*Es ist eine syntaktische Funktion der Shell, daher weist sie ein besonderes Verhalten auf, das "[" nicht hat.
*Variablen müssen nicht mehr quotiert werden, da leere Zeichenfolgen und Zeichenfolgen mit Leerzeichen intuitiver behandelt werden.
*Zum Beispiel müssen Sie mit "[" schreiben.
<pre>
if [ -f "$ FILE"]
</pre>
*um leere Zeichenfolgen oder Dateinamen mit Leerzeichen richtig zu behandeln. Mit "[[" sind die Anführungszeichen unnötig:
<pre>
if [[ -f $ FILE ]]
</pre>
*Da es sich um eine syntaktische Funktion handelt, können Sie && und || verwenden Operatoren für Boolesche Tests und <und> für Zeichenfolgenvergleiche.
*[ kann dies nicht tun, da es sich um einen regulären Befehl handelt und &&, ||, <und> nicht als Befehlszeilenargumente an reguläre Befehle übergeben werden.
 
*Es hat einen wunderbaren Operator = ~, um Übereinstimmungen mit regulären Ausdrücken zu erstellen. Mit [ könntest du schreiben
<pre>
if ["$ ANSWER" = y -o "$ ANSWER" = yes]
</pre>
*Mit [[ können Sie dies als schreiben
<pre>
if [[ $ ANSWER = ~ ^ y (es)? ]]
</pre>
*Sie können sogar auf die erfassten Gruppen zugreifen, die in BASH_REMATCH gespeichert sind.
*Zum Beispiel wäre $ {BASH_REMATCH [1]} "es", wenn Sie oben ein vollständiges "ja" eingeben.
*Sie erhalten die Mustererkennung aka Globbing kostenlos.
*Vielleicht sind Sie weniger streng im Schreiben von Ja. Vielleicht bist du okay, wenn der Benutzer y-irgendetwas eingibt. Haben Sie sich versichert:
*wenn $ ANSWER = y *
 
=Links=
*http://openbook.rheinwerk-verlag.de/shell_programmierung/
*http://mywiki.wooledge.org/BashFAQ/031
*http://tldp.org/LDP/abs/html/index.html
*http://openbook.rheinwerk-verlag.de/shell_programmierung/shell_006_003.htm
*https://kuepper.userweb.mwn.de/informatik/printf.pdf

Aktuelle Version vom 31. Oktober 2026, 07:58 Uhr