Praktische Unterschiede von Bash 5.0 zu Bash 4.4
Seit Januar 2019 ist Bash 5.0 allgemein verfügbar. Dieses aktuelle Major-Release ist ca. 10 Jahre nach dem Major-Release 4 erschienen. In diesem Artikel sollen einige praktische Unterschiede zur vorherigen Version Bash 4.4 aus dem Jahr 2016 dargestellt werden.
Historie
Bei der Bash (Bourne-again Shell) handelt es sich um einen Kommandozeileninterpreter. Die Entwicklung begann 1987 (Brian Fox) für das GNU-Projekt und wurde 1990 von Chet Ramey weitergeführt. Aktuellste Version ist die Version 5.0.
Bash 5.0
In der Hauptsache wurden Bugfixes zur Version 4.4 durchgeführt. Es gibt jedoch auch einige Neuerungen. Die interessantesten werden in diesem Artikel vorgestellt.
Variablen
Anzahl der Sekunden seit der UNIX-Epoche (1.1.1970, Mitternacht UTC/GMT) ; (entspricht „date +%s")
EPOCHREALTIME:
dto. , aber mit zusätzlicher Ausgabe von Mikrosekunden; (entspricht „date +%s.%6N")
BASH_ARGV0:
Name der Shell oder eines ausgeführten Shell-Skripts (Interaktion mit $0)
Beim Ändern der Variablen BASH_ARGV0 wird auch die Variable $0 mit verändert. Grund hierfür ist: beim Debuggen kann es nützlich sein, $0 auf verschiedene Werte zu setzen. Dies führte vor zehn Jahren zum Vorschlag vom BASH Debugger Rocky Bernstein dazu, es in die BASH einzubauen.
Man könnte sich fragen, warum eine neue Variable benötigt wird, anstatt es $0 direkt zuzuweisen. Da 0 jedoch kein gültiger Variablenname ist, wäre es weit aufwändiger es dort einzubauen und auch inkompatibel mit den Vorgängerversionen! Die Variable $0 erlaubt ja nur ihren Wert zu lesen. Vor der BASH 5 konnte es nur beim Starten der Shell gesetzt werden. Mit BASH_ARGV0 kann man den Wert nun sowohl lesen als auch schreiben.
Beispiele:
$ echo $EPOCHSECONDS; date +%s; date -d @$EPOCHSECONDS 1571910528 1571910528 Do 24. Okt 11:48:48 CEST 2019
$ echo $EPOCHREALTIME; date +%s,%6N 1571910528,646358 1571910528,648351
Ändern der $0-Variablen:
$ echo $0 bash $ BASH_ARGV0="Ich bin keine BASH :-)“ $ echo $0 Ich bin keine BASH :-)
Shell Builtin Kommandos
Bei einen Builtin Kommando der Shell handelt es sich um ein Kommando, welches in der Shell eingebaut ist. Diese Kommandos werden im RAM geladen und sind dadurch vom Zugriff schneller im Vergleich zu externen Kommandos, die von der Platte geladen werden müssen. Builtin Kommandos können auch dynamisch geladen werden.
Syntax:
Anzeige, ob Builtin Kommandos enabled/disabled sind
Disabled ein geladenes Builtin Kommando
Enabled ein geladenes Builtin Kommando
Lädt dynamisch ein Builtin Kommando
Entfernt ein dynamisch geladenes Builtin Kommando
Syntax:
enable -a
enable -n name
enable name
enable -f datei name
enable -d name
Die Anzahl der Builtin Kommandos hat sich leicht erhöht (s.u.) und es wurden auch Änderungen an einigen vorhandenen Builtin Kommandos eingebaut:
Shell builtin Kommando history:
Mit diesem Kommando kann man sich die letzten ausgeführten Kommandos (max. $HISTSIZE) anzeigen lassen und auch die History-Liste bearbeiten.
Neu in der BASH 5 ist, dass man nun auch Bereiche entfernen kann, nicht nur wie vorher einzelne Elemente:
Syntax:
history -d START-END
Beim Löschen von einzelnen Elementen lassen sich nun aber auch negative Offsets verwenden.
Beispiele:
Löschen der Einträge 100 bis 200
Löschen der letzten 10 Einträge (genauer von -10 bis -1)
Löschen des 3. letzten Kommandos
$ history -d 100-200
$ history -d -10–-1
$ history -d -3
Shell builtin Kommando wait
Shell Builtin Kommando umask
umask akzeptiert nun auch 4-stellige oktal-Werte - was bei vielen anderen Shells ( ksh, dash, sh, zsh, … ) schon längere Zeit möglich war - wobei aber nur 3 Stellen interpretiert werden:
Beispiel:
$ umask 7777 $ umask 0777
Shell Builtin Kommando times
Dieses Kommando zeigt den Zeitverbrauch an. Es gibt den akkumulierten Benutzer- und Sysemzeitverbrauch der Shell und aller von ihr gestarteten Prozesse aus. Es berücksichtigt jetzt die auch Sprachumgebung, genauer locale, so dass Dezimalzahlen je nach Sprachumgebung mit Punkt oder Komma dargestellt werden, so wie es das Laufzeit-Mess-Kommando „time" schon länger macht.
Beispiel
$ echo $LANG de_DE.UTF-8 $ times 0m0,033s 0m0,049s 0m0,333s 0m0,085s $ LANG=C times 0m0.033s 0m0.049s 0m0.333s 0m0.085s
Es gibt vier neue "loadable" Builtin Kommandos:
rm; stat; fdflags; seq
Diese können aktuell nur eingesetzt werden, wenn man den Quellcode der BASH 5 installiert hat. Dazu müssen sie zuerst per make generiert werden:
# cd /opt/bash-bash-5.0/examples/loadables # make rm # make stat # make fdflags # make seq
Das Builtin Kommando rm arbeitet recht analog zum gleichnamigen Unix Kommando, kennt aber nicht die gleichen Argumente (es fehlen -I -d und -v ).
So werden die generierten Shell-Builtins aktiviert, bzw. deaktiviert:
Beispiel:
# type rm rm is /usr/bin/rm # enable -f /opt/bash-bash-5.0/examples/loadables/rm rm # type rm rm is a shell builtin # enable -d rm # type rm rm is /usr/bin/rm
Das Builtin Kommando stat arbeitet auch analog zum gleichnamigen Unix Kommando, besitzt aber auch nicht die gleichen Optionen. Es schreibt sogar per default die Ausgabe in ein Array dessen Namen man mit der Option -A definieren kann, ansonsten wird der Array-Name STAT verwendet.
Beispiel:
# type stat stat is /usr/bin/stat # enable -f /opt/bash-bash-5.0/examples/loadables/stat stat # type stat stat is a shell builtin # stat /etc/shells # for i in ${!STAT[*]}; do echo -e "$i\t : ${STAT[$i]}"; done nlink : 1 link : /etc/shells perms : 0644 inode : 8401182 blksize : 4096 device : 64768 atime : 1572962369 type : - blocks : 8 uid : 0 size : 90 rdev : 0 name : /etc/shells mtime : 1569869620 ctime : 1569869620 gid : 0 ### Mit der Option -l ist die Ausgabe länger und das Ergebnis besser lesbar: # stat -l /etc/shells # for i in ${!STAT[*]}; do echo -e "$i\t : ${STAT[$i]}"; done nlink : 1 link : /etc/shells perms : u=rw,g=r,o=r inode : 8401182 blksize : 4096 device : 64768 atime : Tue Nov 5 08:59:29 2019 type : - blocks : 8 uid : 0 size : 90 rdev : 0 name : /etc/shells mtime : Mon Sep 30 14:53:40 2019 ctime : Mon Sep 30 14:53:40 2019 gid : 0
Das Builtin Kommando fdflags zeigt an, bzw. ändert Filedeskriptoren eines Ein-/Ausgabekanals.
Das Kommando seq dient dazu Zahlen schrittweise auszugeben. Das Builtin Kommando ist aber nicht so einsatzfähig wie das binäre Kommando:
Beispiel:
$ type seq seq is a shell builtin $ seq 100000 3 100009 100000 100003 100006 100009 $ seq 10000000000000000000 3 10000000000000000009 -9223372036854775808 $ enable -d seq; type seq seq is hashed (/usr/bin/seq) # seq 10000000000000000000 3 10000000000000000009 10000000000000000000 10000000000000000003 10000000000000000006 10000000000000000009
Readline Variable
Wird die Variable completion-ignore-case gesetzt (die schon in der BASH 2 eingeführt wurde) , werden nun auch Shell-Funktionen und Aliase case-insensitv per TAB-Taste erkannt; bisher nur Datei- und Verzeichnisnamen
shopt Optionen (Auswahl)
Bei shopt handelt es sich um ein Builtin Kommando mit dem das Verhalten der Shell geändert werden kann.
Syntax:
$ shopt
- Ohne Option werden alle shopt Optionen angezeigt.
- Mit der Option -s können Optionen auf on (enabled) gesetzt werden.
- Mit der Option -u können Optionen auf off (disabled) gesetzt werden.
Neue bzw. geänderte shopt Optionen:
Neu sind bei Bash 5.0 die folgenden 5 Optionen, so dass nun insgesamt 53 zur Verfügung stehen:
assoc_expand_once off
compat44 off
localvar_inherit off
localvar_unset off
progcomp_alias off
Geändert wurde bei der Bash 5.0 eine Standardeinstellung, die vorher deaktiviert war:
globasciiranges on
Damit werden Bereiche in Klammerausdrücken [..] wie bei C locale ausgewertet.Beispiel:
$ shopt globasciiranges globasciiranges on $ echo $LANG de_DE.UTF-8 $ ls [a-z] a b c d $ ls [A-Z] A B C D
Falls off: Bereiche werden entsprechend der "local collecting sequence" ausgewertet, (d.h. Variable $LANG, genauer locale wird ausgewertet)
Beispiel:
$ shopt -u globasciiranges $ echo $LANG de_DE.UTF-8 $ ls [a-z] a A b B c C d D $ ls [A-Z] A b B c C d D $ LANG=C $ ls [a-z] a b c d $ ls [A-Z] A B C D
Beispiel:
$ cat aA-inherit #!/bin/bash A() { local a echo "A(): a=$a" echo "# Setting a to 100:" a=100 echo "A(): a=$a" } a=1 echo "$0: a=$a" A echo "$0: a=$a" echo "# shopt -s localvar_inherit" shopt -s localvar_inherit # nun wird die Variable a von der Funktion A geerbt: A # die Variable a bleibt in der Basis erhalten: echo "$0: a=$a"
Funktionsaufruf:
$ bash aA-inherit aA-inherit: a=1 A(): a= # Setting a to 100: A(): a=100 aA-inherit: a=1 # shopt -s localvar_inherit A(): a=1 # Setting a to 100: A(): a=100 aA-inherit: a=1
Fazit
Es gibt einige ganz interessante neue Features mit Bash 5.0., z.B.die Möglichkeit, beim buildin-Kommando history ganze Bereiche löschen zu können. Im Vergleich zu der Menge der mit der Version 4 eingeführten Neuerungen ist es aber aktuell noch deutlich weniger …
Es wurden aber auch einige Fehler behoben, die im Laufe der Jahre festgestellt wurden (siehe z.B. www.git.savanah.gnu.org) Es wird noch einige Zeit dauern bis auf allen Linux Distributionen bash 5.0 zur Verfügung steht, da typischerweise gewartet wird, bis sich die Stabilität der Version etabliert hat. Eine der aktuell wenigen Ausnahmen ist "Debian GNU/Linux" der VERSION 10 (buster).
Ansonsten kann man sich die neue Version aus dem Git-Repository hier herunterladen und auf dem System kompilieren und installieren.Senior Chief Consultant bei ORDIX
Bei Updates im Blog, informieren wir per E-Mail.
Kommentare