Wo sind zsh und mksh nicht mit bash kompatibel?


11

Inwieweit können andere POSIX-kompatible Shells als angemessener Ersatz für Bash fungieren? Sie müssen keine echten "Drop-In" -Ersetzungen sein, sondern nahe genug, um mit den meisten Skripten zu arbeiten und den Rest mit einigen Änderungen zu unterstützen.

  1. Ich möchte, dass explizite Bash-Skripte - Initskripte, DHCP-Client-Skripte usw. - mit minimalen Änderungen funktionieren

  2. Ich möchte, dass meine eigene Sammlung spezialisierterer Shell-Skripte nicht zu stark modifiziert wird

  3. Ich möchte Funktionen wie String-Manipulation und eingebauten Regex-Pattern-Matching haben

Die einzigen ernsthaften Konkurrenten, die ich kenne, sind zsh und mksh. Also, für diejenigen von euch hier, die gut mit einem oder beiden sind:

  1. Welche Funktionen hat bash, die zsh und mksh nicht haben?

  2. Welche Funktionen teilen sich die Shells mit bash, verwenden jedoch eine inkompatible Syntax?


3
Vergleich von Befehls-Shells: ( en.wikipedia.org/wiki/Comparison_of_command_shells ) Erweitertes Handbuch für Bash-Scripting: ( tldp.org/LDP/abs/html ) ZSH-Handbuch: ( zsh.sourceforge.net/Guide/zshguide.html ) MirBSD Shell-Handbuch: ( mirbsd.org/htman/i386/man1/mksh.htm ). Es tut mir leid, aber diese Frage ist zu komplex. Vielleicht sollten Sie sich fragen, wie Sie Bash patchen können, um die Sicherheitsanfälligkeit für Ihre spezifische Linux-Distribution zu beheben?
Tyler Maginnis

3
Es gibt keine Shell, die als Ersatz für bashersetzen kann, mksh und zsh können wie /bin/shbei verschiedenen Korrektheitsstufen funktionieren , aber nicht bash.
llua

1
Das ganze Shellshock-Ding scheint nichts mit der Kernfrage zu tun zu haben und lenkt nur die Leute ab, also habe ich es entfernt
Michael Mrozek

3
Die ganze Frage ist zu weit gefasst. Vielleicht solltest du es entfernen.
Tyler Maginnis

1
Die einzige Sorge, die ich wirklich habe, ist, dass BASH von der Free Software Foundation (FSF) gut gepflegt wird. Meine Kontakte dort sagen mir, dass die Aufdeckung des "grundlegenden Fehlers" innerhalb von BASH nur zu einer stärkeren und sichereren Implementierung führen wird. Es gibt so viele alternative Schalen, dass ich sogar anfangen würde, eine für Ihre Anforderung zu empfehlen. Ich würde ein solides Verständnis Ihres Anwendungsfalls erfordern. Dann auf der O / S-Seite ... So viele Dinge hängen mit Bash zusammen, dass Sie möglicherweise Ihre gesamten O / S-Anrufe an BASH umschreiben. Die beste Lösung, die ich sehen kann, ist die Auswahl einer Distribution mit einer gepflegten Alt-Shell.
Tyler Maginnis

Antworten:


19

Ich bleibe bei den Skriptfunktionen. Umfangreiche interaktive Funktionen (Befehlszeilenausgabe, Vervollständigung, Eingabeaufforderungen usw.) sind in der Regel sehr unterschiedlich und erzielen ähnliche Effekte auf völlig inkompatible Weise. Welche Funktionen sind in zsh enthalten und fehlen in bash oder umgekehrt? gibt einige Hinweise zur interaktiven Verwendung.

Am nächsten an Bash wäre ATT ksh93 oder mksh (die Korn-Shell und ein Klon). Zsh hat auch eine Teilmenge von Funktionen, aber Sie müssten es im ksh-Emulationsmodus ausführen, nicht im nativen zsh-Modus.

Ich werde weder POSIX- Funktionen (die in einer modernen shShell verfügbar sind ) noch relativ undurchsichtige Funktionen oder wie oben erwähnt Funktionen für die interaktive Verwendung auflisten. Die Beobachtungen gelten ab Bash 4.2, ksh 93u und mksh 40.9.20120630, wie sie auf Debian Wheezy zu finden sind.

Shell-Syntax

Zitieren

$'…'(Literalstrings mit Backslash-Interpolation) ist in ksh93 und mksh verfügbar. `$" ... "(übersetzte Zeichenfolgen) ist bash-spezifisch.

Bedingte Konstrukte

Mksh und ksh93 müssen ;&in einer caseAnweisung durchfallen , aber ;;&nachfolgende Fälle nicht testen. Mksh hat ;|dafür und aktuelles Mksh ermöglicht ;;&Kompatibilität.

((…))arithmetische Ausdrücke und [[ … ]]Tests sind ksh-Merkmale. Einige bedingte Operatoren unterscheiden sich, siehe „Bedingte Ausdrücke“ weiter unten.

Coprozesse

Ksh und Bash haben beide Coprozesse, aber sie funktionieren unterschiedlich.

Funktionen

Mksh und ksh93 unterstützen function name {…}zusätzlich zum Standard die Syntax für Funktionsdefinitionen. Die name () {…}Verwendung functionin ksh ändert jedoch die Gültigkeitsbereichsregeln. name () …Halten Sie sich daher an die Kompatibilität. Die Regeln für zulässige Zeichen in Funktionsnamen variieren. halte dich an alphanumerische Zeichen und _.

Klammererweiterung

Ksh93 und mksh unterstützen die Erweiterung der Zahnspange {foo,bar}. Ksh93 unterstützt numerische Bereiche {1..42}, mksh jedoch nicht.

Parametererweiterung

Ksh93 und mksh Unterstützung Teilzeichenfolge Extraktion mit ${VAR:offset}und ${VAR:offset:length}, aber nicht Fall Falten wie ${VAR^}, ${VAR,}usw. Sie können mit Fall Konvertierung zu tun typeset -lund typeset -uin beiden bash und ksh.

Sie unterstützen den Ersatz durch ${VAR/PATTERN/STRING}oder ${VAR/PATTERN//STRING}. Die Anführungszeichen für STRING unterscheiden sich geringfügig. Vermeiden Sie daher Backslashes (und möglicherweise andere Zeichen) in STRING (erstellen Sie eine Variable und verwenden Sie sie ${VAR/PATTERN/$REPLACEMENT}stattdessen, wenn die Ersetzung Anführungszeichen enthält).

Array - Erweiterung ( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]}) Arbeit in bash wie in KSH.

${!VAR}Erweitern auf, ${OTHERVAR}wenn der Wert von VARis OTHERVAR(indirekte Variablenreferenz) bash-spezifisch ist (ksh macht etwas anderes mit ${!VAR}). Um diese doppelte Erweiterung in ksh zu erhalten, müssen Sie stattdessen eine Namensreferenz verwenden ( typeset -n VAR=OTHERVAR; echo "$VAR"). ${!PREFIX*}funktioniert genauso.

Prozesssubstitution

Prozessersetzung <(…)und >(…)wird in ksh93, aber nicht in mksh unterstützt.

Platzhaltermuster

Die erweiterten ksh-Glob-Muster, shopt -s extglobdie in bash aktiviert werden müssen , sind immer in ksh93 und mksh verfügbar.

Mksh unterstützt keine Charakterklassen wie [[:alpha:]].

IO-Umleitung

Bash und ksh93 definieren Pseudodateien und , mksh jedoch nicht./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

Das Erweitern von Platzhaltern in einer Umleitung in Skripten (wie beim var="*.txt"; echo hello >$aSchreiben, a.txtwenn dieser Dateiname die einzige Übereinstimmung mit dem Muster ist) ist eine Bash-spezifische Funktion (andere Shells tun dies niemals in Skripten).

<<< Here-Strings funktionieren in ksh wie in bash.

Die Verknüpfung >&zum Umleiten von Syntaxfehlern wird auch von mksh unterstützt, nicht jedoch von ksh93.

Bedingte Ausdrücke

[[ … ]] Syntax mit doppelten Klammern

Die Double-Bracket-Syntax von ksh wird sowohl von ATT ksh93 als auch von mksh wie in bash unterstützt.

Dateibetreiber

Ksh93, mksh und Bash unterstützt die gleichen Erweiterungen POSIX, darunter -aals veraltet Synonym für -e, -k(klebrig), -G(von egid Besitz), -O(Inhaber von euid), -ef(gleicher Datei), -nt(neuer als), -ot(älter als).

-N FILE (geändert seit dem letzten Lesen) wird von mksh nicht unterstützt.

Mksh hat keinen Regexp-Matching-Operator =~. Ksh93 hat diesen Operator und führt den gleichen Abgleich wie in bash durch, hat jedoch nicht das Äquivalent BASH_REMATCH, um übereinstimmende Gruppen anschließend abzurufen.

String-Operatoren

Ksh93 und mksh unterstützen dieselben Zeichenfolgenvergleichsoperatoren <und >als bash sowie das ==Synonym von =. Mksh verwendet keine Gebietsschemaeinstellungen, um die lexikografische Reihenfolge zu bestimmen, sondern vergleicht Zeichenfolgen als Bytezeichenfolgen.

Andere Betreiber

-v VARzu testen, ob eine Variable definiert ist, ist bash-spezifisch. In jeder POSIX-Shell können Sie verwenden [ -z "${VAR+1}" ].

Builtins

alias

Der Satz zulässiger Zeichen in Aliasnamen ist nicht in allen Shells gleich. Ich denke, es ist das gleiche wie für Funktionen (siehe oben).

builtin

Ksh93 hat einen eingebauten Befehl builtin, führt jedoch keinen Namen als eingebauten Befehl aus. Verwenden Sie commanddiese Option, um Aliase und Funktionen zu umgehen. Dies ruft ein eingebautes auf, falls eines vorhanden ist, andernfalls einen externen Befehl (Sie können dies mit vermeiden PATH= command error_out_if_this_is_not_a_builtin).

caller

Dies ist bash-spezifisch. Sie können einen ähnlichen Effekt mit bekommen .sh.fun, .sh.fileund .sh.linenoin ksh93. In mksh gibt es endlich LINENO.

declare, local,typeset

declareist ein bash-spezifischer Name für ksh's typeset. Verwendung typeset: Es funktioniert auch in Bash.

Mksh definiert localals Alias ​​für typeset. In ksh93 müssen Sie typeseteinen Alias verwenden (oder definieren).

Mksh hat keine assoziativen Arrays (sie sind für eine noch nicht veröffentlichte Version vorgesehen).

Ich glaube nicht, dass es typeset -tin ksh ein genaues Äquivalent zu bashs (Trace-Funktion) gibt.

cd

Ksh93 hat nicht -e.

echo

Ksh93 und mksh verarbeiten die Optionen -eund -nwie in bash. Mksh versteht auch -E, dass ksh93 es nicht als Option behandelt. Die Backslash-Erweiterung ist in ksh93 standardmäßig deaktiviert, in mksh standardmäßig aktiviert.

enable

Ksh bietet keine Möglichkeit, integrierte Befehle zu deaktivieren. Um eine integrierte Funktion zu vermeiden, suchen Sie den Pfad des externen Befehls und rufen Sie ihn explizit auf.

exec

Ksh93 hat -aaber nicht -l. Mksh hat keine.

export

Weder ksh93 noch mksh haben export -n. Verwenden Sie typeset +x foostattdessen, es funktioniert in bash und ksh.

Ksh exportiert keine Funktionen durch die Umgebung.

let

let ist das gleiche in bash und ksh.

mapfile, readarray

Dies ist eine Bash-spezifische Funktion. Sie können while readSchleifen oder Befehlssubstitution verwenden, um eine Datei zu lesen und in ein Array von Zeilen aufzuteilen. Pass auf dich auf IFSund globbing. Hier ist das Äquivalent von mapfile -t lines </path/to/file:

IFS=$'\n'; set -f
lines=($(</path/to/file))
unset IFS; set +f

printf

printfist sehr ähnlich. Ich denke, ksh93 unterstützt alle Formatanweisungen von bash. mksh unterstützt nicht %qoder %(DATE_FORMAT)T; Bei einigen Installationen printfist kein mksh integriert und ruft stattdessen den externen Befehl auf.

printf -v VAR ist bash-spezifisch, ksh druckt immer auf Standardausgabe.

read

Einige Optionen sind bash-spezifisch, einschließlich aller Optionen für readline. Die Optionen -r, -d, -n, -N, -t, -usind identisch in bash, ksh93 und mksh.

readonly

Sie können eine Variable in Ksh93 und mksh mit derselben Syntax als schreibgeschützt deklarieren. Wenn es sich bei der Variablen um ein Array handelt, müssen Sie sie zuerst zuweisen und dann schreibgeschützt machen readonly VAR. Funktionen können in ksh nicht schreibgeschützt werden.

set, shopt

Alle Optionen für setund set -osind POSIX- oder ksh-Funktionen.

shoptist bash-spezifisch. Viele Optionen betreffen ohnehin die interaktive Nutzung. Informationen zu Auswirkungen auf das Globbing und andere Funktionen, die durch einige Optionen aktiviert werden, finden Sie im Abschnitt „Optionen“ weiter unten.

source

Diese Variante von .existiert auch in ksh. sourceDurchsucht in bash und mksh das aktuelle Verzeichnis nach PATH, in ksh93 ist es jedoch genau das Äquivalent von ..

trap

Das DEBUGPseudosignal ist in mksh nicht implementiert. In ksh93 gibt es eine andere Möglichkeit, Informationen zu melden. Weitere Informationen finden Sie im Handbuch.

type

In ksh typeist ein Alias ​​für whence -v. Gibt in mksh type -pnicht den Pfad zur ausführbaren Datei aus, sondern eine für Menschen lesbare Nachricht. Sie müssen whence -p COMMANDstattdessen verwenden.

Optionen

shopt -s dotglob - Punktdateien beim Globbing nicht ignorieren

Um die dotglobOption in ksh93 zu emulieren , können Sie festlegen FIGNORE='@(.|..)'. Ich glaube nicht, dass es so etwas in mksh gibt.

shopt -s extglob - ksh erweiterte Glob-Muster

Die extglobOption ist in ksh effektiv immer aktiviert.

shopt -s failglob - Fehler aus, wenn ein Glob-Muster mit nichts übereinstimmt

Ich glaube nicht, dass dies in mksh oder ksh93 existiert. Dies geschieht in zsh (Standardverhalten, sofern nicht festgelegt null_globoder csh_null_globfestgelegt).

shopt -s globstar**/rekursives Globbing

Ksh93 hat rekursives Globbing mit **/, aktiviert mit set -G. Mksh hat kein rekursives Globbing.

shopt -s lastpipe - Führen Sie den letzten Befehl einer Pipeline in der übergeordneten Shell aus

Ksh93 führt immer den letzten Befehl einer Pipeline in der übergeordneten Shell aus, für die in bash die lastpipeOption festgelegt werden muss. Mksh führt immer den letzten Befehl einer Pipeline in einer Subshell aus.

shopt -s nocaseglob, shopt -s nocasematch- Muster ohne Berücksichtigung der Groß- und Kleinschreibung

Mksh hat keinen Mustervergleich, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird. Ksh93 unterstützt es Muster für Muster: Stellen Sie dem Muster das Präfix vor ~(i).

shopt -s nullglob - Erweitern Sie Muster, die keiner Datei entsprechen, mit einer leeren Liste

Mksh hat das nicht. Ksh93 unterstützt es Muster für Muster: Stellen Sie dem Muster das Präfix vor ~(N).

Variablen

Offensichtlich existieren die meisten BASH_xxxVariablen nicht in ksh. $BASHPIDkann mit dem teuren, aber tragbaren sh -c 'echo $PPID'Gerät emuliert werden und wurde kürzlich zu mksh hinzugefügt. BASH_LINEist .sh.linenoin ksh93 und LINENOin mksh. BASH_SUBSHELList .sh.subshellin ksh93.

Mksh und ksh93 beziehen beide die ENVbeim Start angegebene Datei .

EUIDund UIDexistieren nicht in ksh93. Mksh nennt sie USER_IDund KSH_UID; es hat nicht GROUPS.

FUNCNAMEund FUNCNESTexistieren nicht in ksh. Ksh93 hat .sh.funund .sh.level. Mit function foo { …; }(keine Klammern!) Deklarierte Funktionen haben ihren eigenen Namen in $0.

GLOBIGNOREexistiert in ksh93, aber mit einem anderen Namen und einer anderen Syntax: Es heißt FIGNOREund es ist ein einzelnes Muster, keine durch Doppelpunkte getrennte Liste. Verwenden Sie ein @(…|…)Muster. Ksh's fasst FIGNOREBashs mit einer völlig anderen Syntax zusammen.

Ksh93 und mksh haben nichts Vergleichbares HOSTTYPE, MACHTYPEund OSTYPE. Noch SHELLOPTSoder TIMEFORMAT.

Mksh hat PIPESTATUS, aber ksh93 nicht.

Mksh und ksh93 haben RANDOM.


Wenn Sie die (nicht eingetragene) Marke "mksh" am Anfang eines Satzes nicht korrekt wiedergeben möchten ( siehe auch "dd." vs. "dd" hier ), schreiben Sie bitte "The MirBSD" Korn Shell “stattdessen. Es ist immer falsch , einen Buchstaben von "mksh" groß zu schreiben. Vielen Dank.
Mirabilos

Wie kann $BASHPIDmit emuliert werden sh -c 'echo $PPID'? Ich habe es (sh -c 'echo $PPID')in Bash versucht, aber es gibt mir die gleiche PID wie $$.
Franklin Yu

Ich denke, die Frage passt hier besser . Ich habe die Frage dort kopiert.
Franklin Yu

4

Diese Frage ist eher zu weit gefasst.

Sowohl mksh als auch zsh sind Shells, die viele GNU-Bash- spezifische Erweiterungen unterstützen, aber es gibt immer einige, die nicht verstanden werden.

zsh unterstützt mehr Dinge, aber nur in seinem nativen zsh-Modus, der nicht mit POSIX-Shells kompatibel ist (wie GNU bash, AT & T ksh93 , mksh). Außerdem ist mksh viel schlanker und schneller und tragbarer.

Wenn es sich um Ihre Skripte handelt, über die wir sprechen, testen Sie sie im Allgemeinen . (mksh unterstützt noch keine assoziativen Arrays im bash4-Stil. Der Befehl "declare" ist bash-spezifisch, "typeset" ist ein Äquivalent. Ich bin mit zsh nicht vertraut genug, um etwas darüber zu sagen. ksh93 hat kein "local" verwendet aber auch "Schriftsatz" dafür.) Aber wenn es beispielsweise darum geht, ein Debian-System ohne Bash auszuführen, vergessen Sie es. Die Existenz von Bash ist Teil des „Versprechens“ (API / ABI des Systems) und hängt viel davon ab.

Haftungsausschluss: Ich bin der mksh-Entwickler.


1

ZSH-Muschelvergleich

In den letzten Jahren gab es jedoch eine gewisse Überkreuzung in den Erweiterungen. Zsh (ab 3.1.6) hat Bashs ${var/old/new}' feature for replacing the text old with the text new in the parameter $var. Note one difference here: while both shells implement the syntax$ {var / # old / new} 'und ${var/%old/new}' for anchoring the match of old to the start or end of the parameter text, respectively, in zsh you can't put the#' oder %' inside a parameter: in other words{var / $ old / new} ', wobei old mit einem #' treats that as an ordinary character in zsh, unlike bash. To do this sort of thing in zsh you can use (from 3.1.7) the new syntax for anchors in any pattern,(#s)' beginnt , um dem Anfang eines Strings zu entsprechen und `(#e) 'passend zum Ende. Hierfür muss die Option EXTENDED_GLOB gesetzt sein.

Ich bin mit mksh am wenigsten vertraut, daher weiß ich nicht, wo ich nach dieser Antwort suchen soll.

Wenn Sie nach einem sicheren Ersatz für die Shell suchen, unterscheidet sich keine dieser Shells stark von Bash, was den inhärenten Fehler betrifft, den Sie diskutieren.

Eine Sprache wie Perl verarbeitet Eingaben sicherer. Aber auch hier ist die Wartbarkeit von entscheidender Bedeutung. Der Perl-Shell-Ersatz ist nicht sehr gut angenommen. Es liegt in der Verantwortung des Shell-Betreuers, Eingaben sicher zu verarbeiten. Wenn Sie also Skripte schreiben, validieren, validieren, validieren Sie alles! Verwenden Sie Codeverträge, um jedes Mal korrekte Ergebnisse sicherzustellen!

Perl Shell

FSF-Erklärung zu Shell Shock


Wenn es wirklich so ist, dass andere Shells den gleichen Fehler haben - was ich aufgrund meiner Diskussion etwas bezweifle -, dann ist das ein RIESIGES Problem, da viele Programme von Drittanbietern Variablen ohne jegliche Art an die Shell übergeben der Validierung oder irgendetwas. In diesem Fall können wir POSIX genauso gut komplett wegwerfen.
DanL4096

1
Das Bash-Projekt wurde in 10 Jahren 1 0-Tage-Exploit durchgeführt. Microsoft Windows verfügt über mehr als 10 Exploits an allen 0 Tagen pro Woche. Wissen Sie überhaupt, wie viele Leute das Bash-Entwicklungsteam darüber gestört haben? Einfach aktualisieren und weitermachen! Es ist keine große Sache.
Tyler Maginnis

1
@ DanL4096. Das Übergeben von Variablen an Shell-Skripte, die dann die Variablen nicht ausreichend überprüfen, ist kein Grund, POSIX zu verwerfen. Das Problem liegt bei der Person, die das Shell-Skript überhaupt geschrieben hat.
fpmurphy

0

Eine Funktion, die in nicht standardmäßig aktiviert mkshist, ist der Shell-Verlauf.

  • In Ihrem .mkshrcgerade eingestellten:

    export HISTFILE=~/.mksh-history

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.