Wissen/Bourne Shell

Aus UUGRN

Bourne-Shell: Geschichte und Grundlagen

Teil 1: Geschichte

Thompson-Shell

  • Erste Shell für AT&T UNIX (“UNICS”) Version 1 bis 6
  • Name des Programms: “sh” (liegt im Verzeichnis “/bin”). Also lautet der absolute Pfadname /bin/sh,
  • Aufgaben:
    • Starten von Programmen
    • Umleiten von Ausgaben (“Redirection”) in andere Programme (“Filter”) oder in Dateien.
  • Siehe auch Manpage https://www.in-ulm.de/~mascheck/bourne/v3/

Bourne-Shell

  • Nachfolger der Thompson-Shell ab AT&T UNIX Version 7.
  • Hauptaugenmerk auf “Command Language” (mit Bedingunge, Schleifen u.v.a.m.).
    • Syntax der Sprache inspiriert von ALGOL68.
  • Außerdem können Shell-Skripten selbst Filter sein (ging bei Thompson Shell nicht).
  • Seit 1989 quasi quasi unverändert, vergleiche auch: https://en.wikipedia.org/wiki/Bourne_shell#Features_introduced_after_1979
  • Code der Bourne Shell war die Inspiration für den International Obfuscated C Code Contest".

C-Shell

  • Entwickelt von der “Berkeley Group” (BSD) als Alternative zu Bourne Shell.
  • Inspiriert von C-Syntax.
  • Komfortabler als die Bourne Shell für interaktive Benutzung.
  • Gilt inzwischen als veraltet (“C Shell Programming considered harmful”).

Korn-Shell

Bourne-Again-Shell

  • Autragsarbeit eines Festangestellten der Free Software Foundation für das GNU-Projekt.
    • Auf BSD nicht standardmäßig installiert bzw. oft in /usr/local/bin o.ä.
  • Kompatibel zu Bourne Shell:
    • Spezieller Kompatibilitätsmodus wenn als “sh” aufgerufen
  • Arrays.
  • “shopt” statt “set” für Bash-spezifische Optionen
  • Stark erweiterte Parameter-Expansion
    • z.B. Substitution,
    • Siehe Manpage.
  • Verbesserte Arithmetik.
  • Erweiterte Redirection.
  • Sehr stark verbesserter interaktiver Modus ähnlich Korn Shell.

Almquist-Shell (“ash” bzw. “dash”)

  • Reimplementation der Bourne Shell unter anderer Lizenz.
  • Zuerst für BSD, später portiert auf Debian (dort “dash”).

Z-Shell

  • Reimplementation der Bourne Shell mit stark erweiterten Features.
  • Empfohlen als interaktive, nicht aber als nicht-interaktive Shell.
    • Grund: Shell-Skripten in zsh setzen installierte zsh voraus.

Kompatibilität

  • Kern: Bourne Shell (und deshalb meine Empfehlung).
  • Vorsicht: In "Bourne-kompatiblen" Shells kann man Code schreiben, der in Bourne nicht geht.

Teil 2: Grundlagen

Funktionsweise

  • Betriebsmodus “interaktiv”.
    • Spezialfall “Login-Shell”.
    • Zeilenweise Ein- und Ausgabe über ein tty (“Teletype”, Printer, serielle Schnittstelle, Terminal, Terminal Emulator).
  • Betriebsmodus “non-interaktiv”
  • “Shebang”-Konvention in Skripten (erste Zeile #!/bin/sh).
  • Kommentare
  • Line Continuation
  • Shell-Optionen, die den Betriebsmodus verändern (z.B. -e, -x)
  • Zeilenbasierter Parser
  • Expansionen
    • Siehe dazu z.B. die Manpage von “dash”, Abschnitt “Word Expansions”
  • Kontrollstrukturen
  • Redirection und Pipes

Grundsätzliche Features

  • “Strings are first-class citizens and the only citizens” – Stephen Bourne
  • Es gibt kein “goto” (Bourne ist ALGOL-Fan)
  • Hauptaufgaben:
    • Zuweisungen
      • Spezialfall: “export”
    • Kommandos ausführen
      • builtins vs. executables
  • Variablen:
    • Einfach: “foo=bar”
    • Export an Subprozesse: “export FOO=bar”
    • Zugriff auf den Wert der Variable:
      • echo "$foo" (“verkürzte Syntax”)
      • echo "${foo}" (“vollständige Syntax”)
    • Variablen mit Bedeutung für die Shell selbst (Beispiele): PATH, PS1, IFS, …
    • “Interessante” Umgebungsvariablen: PATH, USER, SHELL, PPID, …
  • Expansion:
    • Gute Übersicht:

https://www.gnu.org/software/bash/manual/html_node/Shell-Expansions.html

    • Besonders wichtig: Parameter-Expansion:
      • Kommandozeilen-Argumente $*, $@ und $0, $1, …
      • Spezial-Features mit “ausführlicher Syntax”:
        • config=${1:-config.inc}:

“Der Wert der Variable”config" ist der Wert des ersten Kommandozeilen-Arguments, es sei denn, dieses wäre leer oder nicht gesetzt, dann soll der Wert ‘config.inc’ lauten."

      • Bourne Shell hat noch andere interessante Parameter-Exansion-Tricks, und Bourne Again Shell noch viel mehr.
    • Wichtig: Command Substitution:
    • Mit Backticks:
  output=`ls | grep foo`
    • oder mit Klammerung:
  output=$(ls | grep foo)
    • Die geklammerte Syntax hat u.a. den Vorteil, dass sie einfacher verschachtelt werden kann.
    • Nützlich: Arithmetik (nur Ganzzahlen): a=0 ; a=$((a+2)) ; echo $a
  • Arbeiten mit Rückgabewerten
    • Abgespeichert in $?
    • Konvention: 0: Erfolg; Sonst: Fehler.
  • Quotierung
    • Klassisch mit ", desweiteren auch mit '
    • Spezialfall: Here-Documents
  sed -e 's/foo/bar/g' << EOF
  Ein foo kam daher
  zum foo und danach noch zu einem anderen foo. 
  EOF
    • Hinweis: Here-Documents kamen im Vortrag aus Zeitgründen nicht dran.
    • Herausforderung: Escaping:
    • Beispiel 1: echo "\"Doppelte\" Anführungszeichen"
    • Beispiel 2: echo '\'Einfache\' Anführungszeichen'
  • Kontrollstrukturen:
    • if true ; then echo "passt." ; else echo "komisch" ; fi
    • bzw. auf mehreren Zeilen:
  if true ; then
     echo "passt"
  else
     echo "komisch"
  fi
  • while true ; do echo "idle ..." ; sleep 1 ; done
  • bzw.
  while true ; do
     echo "idle ..."
  done
  • Generell:
    • Interaktiver Modus: Einzeiler-Syntax.
    • Non-Interaktiver Modus/Skript: Mehrzeilige Syntax.
  • Funktionen definieren
    • Bourne und Bourne Again Shell: xxx() { echo "xxx" ; }
    • Nur Bourne Again Shell: function xxx() { echo "xxx" ; }
    • Empfehlung: Bourne Syntax verwenden, da vorwärtskompatibel.
  • Source Files
    • Hinweis: Kam im Vortrag aus Zeitgrpnden nicht dran.
    • Inhalt einer anderen Datei an dieser Stelle komplett als Shellcode laden und ausführen.
    • Beispiel: . /usr/local/lib/shell-stuff/config.sh
    • Problem (u.a.): . ./config.sh (Welcher Speicherort von “config.sh” wird hier erwartet?)

Anhang: Das Beispiel "deltmp.sh" aus dem Vortrag

  #!/bin/sh
  # set -e
  dir=${1:-/tmp}
  if find "$dir" -name '*.tmp' > /tmp/find.log 2> /tmp/find.err ; then
     echo "Ausgabe abgeschlossen am $(date)" >> /tmp/find.log
  else
     echo "Fehler beim Durchsuchen am $(date)" >> /tmp/find.log
  fi

Links

Geschichte

Benutzung