Dove sono zsh e mksh incompatibili con bash?


11

In che misura altre shell compatibili con POSIX possono funzionare come sostituti ragionevoli di bash? Non hanno bisogno di essere veri e propri sostituti "drop-in", ma abbastanza vicini da funzionare con la maggior parte degli script e supportare il resto con qualche modifica.

  1. Voglio che gli script bash espliciti - initscripts, script client DHCP, ecc. - funzionino con una modifica minima

  2. Voglio che la mia raccolta di script shell più specializzati non abbia bisogno di troppe modifiche

  3. Voglio avere funzionalità come la manipolazione delle stringhe e la corrispondenza del pattern regex incorporato

Gli unici contendenti seri che conosco sono zsh e mksh. Quindi, per quelli di voi qui che sono bravi con uno o entrambi:

  1. Quali caratteristiche ha bash che rispettivamente zsh e mksh non hanno?

  2. Quali caratteristiche condividono le shell con bash, ma usano sintassi incompatibili?


3
Confronto di shell di comando: ( en.wikipedia.org/wiki/Comparison_of_command_shells ) Guida avanzata agli script di Bash: ( tldp.org/LDP/abs/html ) Manuale ZSH: ( zsh.sourceforge.net/Guide/zshguide.html ) MirBSD Shell Manual: ( mirbsd.org/htman/i386/man1/mksh.htm ). Mi dispiace, ma questa domanda è troppo complessa. Forse dovresti chiedere come patchare bash per correggere la vulnerabilità all'interno della tua specifica distribuzione di Linux?
Tyler Maginnis,

3
Non esiste una shell che può funzionare come un calo in sostituzione di bash, mksh e zsh possono funzionare come /bin/shcon vari livelli di correttezza, ma non bash.
llua

1
L'intera cosa dello shellshock sembra non avere nulla a che fare con la domanda principale e sta solo distraendo le persone, quindi l'ho rimosso
Michael Mrozek

3
L'intera questione è eccessivamente ampia. Forse dovresti rimuoverlo.
Tyler Maginnis,

1
L'unica preoccupazione che ho davvero è che BASH è ben gestito dalla Free Software Foundation (FSF). I miei contatti lì mi dicono che la rivelazione del "difetto fondamentale" all'interno di BASH porterà a un'implementazione più forte e più sicura. Ci sono così tante shell alternative che anche iniziando a raccomandarne una per le tue esigenze, richiederei una solida conoscenza del tuo caso d'uso. Quindi dal lato O / S ... Tante cose sono legate a Bash che potresti finire per riscrivere tutte le tue chiamate O / S a BASH. La migliore soluzione che posso vedere è quella di scegliere una distribuzione con un alt-shell mantenuto.
Tyler Maginnis,

Risposte:


19

Seguirò le funzionalità di scripting. Le funzionalità interattive avanzate (edizione della riga di comando, completamento, istruzioni, ecc.) Tendono ad essere molto diverse, ottenendo effetti simili in modi totalmente incompatibili. Quali caratteristiche sono in zsh e mancano da bash o viceversa? fornisce alcuni suggerimenti sull'uso interattivo.

La cosa più vicina a bash sarebbe ATT ksh93 o mksh (la shell Korn e un clone). Zsh ha anche un sottoinsieme di funzionalità, ma dovresti eseguirlo in modalità di emulazione ksh, non in modalità nativa zsh.

Non elencherò le funzionalità POSIX (che sono disponibili in qualsiasi shshell moderna ), né le funzionalità relativamente oscure, né quelle menzionate sopra per uso interattivo. Le osservazioni sono valide da bash 4.2, ksh 93u e mksh 40.9.20120630 come si trova su Debian wheezy.

Sintassi della shell

citando

$'…'(stringhe letterali con interpolazione barra rovesciata) è disponibile in ksh93 e mksh. `$" ... "(stringhe tradotte) è specifico per bash.

Costrutti condizionali

Mksh e ksh93 devono ;&passare attraverso una casedichiarazione, ma non ;;&per testare i casi successivi. Mksh ha ;|questo e il recente mksh consente la ;;&compatibilità.

((…))espressioni e [[ … ]]test aritmetici sono caratteristiche di ksh. Alcuni operatori condizionali sono diversi, vedere "espressioni condizionali" di seguito.

Coprocesses

Ksh e bash hanno entrambi coprocessi ma funzionano in modo diverso.

funzioni

Mksh e ksh93 supportano la function name {…}sintassi per le definizioni delle funzioni oltre allo standard name () {…}, ma l'uso functionin ksh modifica le regole di scoping, quindi attenersi name () …a mantenere la compatibilità. Le regole per i caratteri consentiti nei nomi delle funzioni variano; attenersi agli alfanumerici e _.

Espansione del rinforzo

Ksh93 e mksh supportano l'espansione del controvento {foo,bar}. Ksh93 supporta intervalli numerici {1..42}ma mksh no.

Espansione dei parametri

Ksh93 e supporto mksh estrazione di sottostringa con ${VAR:offset}e ${VAR:offset:length}, ma non caso pieghevole come ${VAR^}, ${VAR,}, ecc Si può fare la conversione caso typeset -le typeset -usia in bash e ksh.

Supportano la sostituzione con ${VAR/PATTERN/STRING}o ${VAR/PATTERN//STRING}. Le regole di quotazione per STRING sono leggermente diverse, quindi evita le barre rovesciate (e forse altri caratteri) in STRING (costruisci una variabile e usa ${VAR/PATTERN/$REPLACEMENT}invece se la sostituzione contiene caratteri di quotazione).

Espansione dell'array ( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]}) opera in bash come in ksh.

${!VAR}espandendosi a ${OTHERVAR}quando il valore di VARis OTHERVAR(riferimento variabile indiretto) è specifico di bash (ksh fa qualcosa di diverso con ${!VAR}). Per ottenere questa doppia espansione in ksh, devi invece usare un riferimento al nome ( typeset -n VAR=OTHERVAR; echo "$VAR"). ${!PREFIX*}funziona allo stesso modo.

Sostituzione del processo

Sostituzione del processo <(…)ed >(…)è supportato in ksh93 ma non in mksh.

Modelli jolly

I modelli glob estesi ksh che devono shopt -s extglobessere attivati ​​in bash sono sempre disponibili in ksh93 e mksh.

Mksh non supporta classi di personaggi come [[:alpha:]].

Reindirizzamento IO

Bash e ksh93 definiscono pseudo-file e , ma mksh no./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

Espandere i caratteri jolly in un reindirizzamento negli script (come per var="*.txt"; echo hello >$aiscritto a.txtse quel nome file è l'unica corrispondenza per il modello) è una funzione specifica di bash (altre shell non lo fanno mai negli script).

<<< qui-stringhe funzionano in ksh come in bash.

Il collegamento >&per reindirizzare gli errori di sintassi è supportato anche da mksh ma non da ksh93.

Espressioni condizionali

[[ … ]] sintassi doppia parentesi

La sintassi della doppia parentesi di ksh è supportata sia da ATT ksh93 che da mksh come in bash.

Operatori di file

Ksh93, mksh e bash supportano le stesse estensioni di POSIX, incluso -acome sinonimo obsoleto di -e, -k(appiccicoso), -G(di proprietà di egid), -O(proprietario di euid), -ef(stesso file), -nt(più recente di), -ot(più vecchio di).

-N FILE (modificato dall'ultima lettura) non è supportato da mksh.

Mksh non ha un operatore di abbinamento regexp =~. Ksh93 ha questo operatore ed esegue la stessa corrispondenza di in bash, ma non ha un equivalente di BASH_REMATCHrecuperare gruppi corrispondenti in seguito.

Operatori di stringa

Ksh93 e mksh supportano gli stessi operatori di confronto di stringhe <e >come bash e il ==sinonimo di =. Mksh non usa le impostazioni locali per determinare l'ordine lessicografico, confronta le stringhe come stringhe di byte.

Altri operatori

-v VARverificare se una variabile è definita è specifico di bash. In qualsiasi shell POSIX, è possibile utilizzare [ -z "${VAR+1}" ].

builtins

alias

L'insieme di caratteri consentiti nei nomi di alias non è lo stesso in tutte le shell. Penso che sia lo stesso delle funzioni (vedi sopra).

builtin

Ksh93 ha un builtin chiamato builtin, ma non esegue un nome come comando incorporato. Utilizzare commandper bypassare alias e funzioni; questo chiamerà un builtin se ne esiste uno, altrimenti un comando esterno (puoi evitarlo con PATH= command error_out_if_this_is_not_a_builtin).

caller

Questo è specifico per Bash. È possibile ottenere un effetto simile con .sh.fun, .sh.filee .sh.linenoin ksh93. In mksh c'è finalmente LINENO.

declare, local,typeset

declareè un nome specifico per bash per ksh typeset. Usa typeset: funziona anche in bash.

Mksh definisce localcome un alias per typeset. In ksh93, devi usare typeset(o definire un alias).

Mksh non ha array associativi (sono previsti per una versione non ancora pubblicata).

Non penso che esista un equivalente esatto di bash typeset -t(funzione trace) in ksh.

cd

Ksh93 non ha -e.

echo

Ksh93 e mksh elaborano le opzioni -ee -ncome in bash. Mksh capisce anche che -Eksh93 non lo considera un'opzione. L'espansione della barra rovesciata è disattivata per impostazione predefinita in ksh93, attivata per impostazione predefinita in mksh.

enable

Ksh non fornisce un modo per disabilitare i comandi integrati. Per evitare un built-in, cerca il percorso del comando esterno e invocalo esplicitamente.

exec

Ksh93 ha -ama non -l. Mksh non ha nessuno dei due.

export

Né ksh93 né mksh hanno export -n. Usa typeset +x fooinvece, funziona in bash e ksh.

Ksh non esporta le funzioni attraverso l'ambiente.

let

let è lo stesso in bash e ksh.

mapfile, readarray

Questa è una funzione specifica per bash. È possibile utilizzare i while readloop o la sostituzione dei comandi per leggere un file e dividerlo in una matrice di righe. Abbi cura di te IFSe del dolore. Ecco l'equivalente di mapfile -t lines </path/to/file:

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

printf

printfè molto simile. Penso che ksh93 supporti tutte le direttive sul formato di Bash. mksh non supporta %qo %(DATE_FORMAT)T; su alcune installazioni, printfnon è un mksh incorporato e chiama invece il comando esterno.

printf -v VAR è specifico per bash, ksh stampa sempre sullo standard output.

read

Diverse opzioni sono specifiche di bash, comprese tutte quelle su readline. Le opzioni -r, -d, -n, -N, -t, -usono identici in bash, ksh93 e mksh.

readonly

Puoi dichiarare una variabile di sola lettura in Ksh93 e mksh con la stessa sintassi. Se la variabile è un array, è necessario prima assegnarlo, quindi renderlo di sola lettura con readonly VAR. Le funzioni non possono essere rese di sola lettura in ksh.

set, shopt

Tutte le opzioni per sete set -osono POSIX o ksh.

shoptè specifico per bash. Molte opzioni riguardano comunque l'uso interattivo. Per effetti sul globbing e altre funzionalità abilitate da alcune opzioni, vedere la sezione "Opzioni" di seguito.

source

Questa variante .esiste anche in ksh. In bash e mksh, sourcecerca la directory corrente dopo PATH, ma in ksh93, è un equivalente esatto di ..

trap

Lo DEBUGpseudo-segnale non è implementato in mksh. In ksh93, esiste un modo diverso per riportare informazioni, vedere il manuale per i dettagli.

type

In ksh, typeè un alias per whence -v. In mksh, type -pnon stampa il percorso dell'eseguibile, ma un messaggio leggibile dall'uomo; devi usare whence -p COMMANDinvece.

Opzioni

shopt -s dotglob - non ignorare i file di punti in globbing

Per emulare l' dotglobopzione in ksh93, puoi impostare FIGNORE='@(.|..)'. Non penso che ci sia qualcosa di simile in Mksh.

shopt -s extglob - ksh modelli glob estesi

L' extglobopzione è effettivamente sempre attiva in ksh.

shopt -s failglob - errore se un modello glob non corrisponde a nulla

Non penso che questo esista in mksh o ksh93. Lo fa in zsh (comportamento predefinito a meno null_globche non sia csh_null_globimpostato).

shopt -s globstar**/globbing ricorsivo

Ksh93 ha globbing ricorsivo con **/, abilitato con set -G. Mksh non ha globbing ricorsivo.

shopt -s lastpipe - esegue l'ultimo comando di una pipeline nella shell padre

Ksh93 esegue sempre l'ultimo comando di una pipeline nella shell padre, che in bash richiede che l' lastpipeopzione sia impostata. Mksh esegue sempre l'ultimo comando di una pipeline in una subshell.

shopt -s nocaseglob, shopt -s nocasematch- modelli senza distinzione tra maiuscole e minuscole

Mksh non ha una corrispondenza di pattern senza distinzione tra maiuscole e minuscole. Ksh93 lo supporta in base al modello: prefisso il modello con ~(i).

shopt -s nullglob - espande i motivi che non corrispondono ad alcun file in un elenco vuoto

Mksh non ha questo. Ksh93 lo supporta in base al modello: prefisso il modello con ~(N).

variabili

Ovviamente la maggior parte delle BASH_xxxvariabili non esiste in ksh. $BASHPIDpuò essere emulato con il costoso ma portatile sh -c 'echo $PPID', ed è stato recentemente aggiunto a mksh. BASH_LINEè .sh.linenoin ksh93 e LINENOin mksh. BASH_SUBSHELLè .sh.subshellin ksh93.

Mksh e ksh93 hanno entrambi il file sorgente dato ENVall'avvio.

EUIDe UIDnon esistono in ksh93. Mksh li chiama USER_IDe KSH_UID; non ha GROUPS.

FUNCNAMEe FUNCNESTnon esistono in ksh. Ksh93 ha .sh.fune .sh.level. Le funzioni dichiarate con function foo { …; }(nessuna parentesi!) Hanno il loro nome in $0.

GLOBIGNOREesiste in ksh93 ma con un nome e una sintassi diversi: si chiama FIGNOREed è un singolo modello, non un elenco separato da due punti. Usa uno @(…|…)schema. Ksh sottrae FIGNOREbash, con una sintassi completamente diversa.

Ksh93 e mksh hanno nulla di simile HOSTTYPE, MACHTYPEe OSTYPE. Né SHELLOPTSo TIMEFORMAT.

Mksh ha PIPESTATUS, ma ksh93 no.

Mksh e Ksh93 hanno RANDOM.


se non si desidera riprodurre correttamente il marchio (non registrato) "mksh" all'inizio di una frase ( vedere anche "" dd. "" vs. "" dd "." qui ), si prega di scrivere "The MirBSD Korn Shell "invece. È sempre sbagliato capitalizzare qualsiasi lettera di "mksh". Grazie.
mirabilos,

Come si può $BASHPIDemulare sh -c 'echo $PPID'? Ho provato (sh -c 'echo $PPID')a Bash ma mi dà lo stesso PID di $$.
Franklin Yu,

Penso che la domanda si adatti meglio qui . Ho copiato la domanda lì.
Franklin Yu,

4

Questa domanda è piuttosto troppo ampia.

Sia mksh che zsh sono shell che supportano molte estensioni specifiche per GNU bash , ma ce ne sono sempre alcune che non sono comprese.

zsh supporta più cose, ma solo nella sua modalità zsh nativa, che non è compatibile con le shell POSIX (come GNU bash, AT&T ksh93 , mksh). Inoltre, mksh è molto più snello, più veloce e più portatile.

In generale, se questi sono i tuoi script di cui stiamo parlando, vai avanti, provali. (mksh non supporta ancora matrici associative in stile bash4. Il comando "declare" è specifico per bash, "typeset" è un equivalente. Non ho abbastanza familiarità con zsh per dichiarare nulla di tutto ciò. ksh93 non ha "local" ma usa anche "impaginazione" per questo.) Ma se si tratta, diciamo, di eseguire un sistema Debian senza bash, dimenticalo. L'esistenza di bash fa parte della "promessa" (API / ABI del sistema) e si basa molto su di essa.

Disclaimer: sono lo sviluppatore di mksh.


1

ZSH Confronto di conchiglie

Negli ultimi anni, tuttavia, c'è stato un certo crossover nelle estensioni. Zsh (al 3.1.6) ha ${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} di bash e ${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# 'o %' inside a parameter: in other words{var / $ old / new}' dove old inizia con un #' 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) 'per abbinare l'inizio di una stringa e `(#e) 'per corrispondere alla fine. Questi richiedono che sia impostata l'opzione EXTENDED_GLOB.

Non ho molta familiarità con mksh, quindi non so dove cercare quella risposta.

Se stai cercando un sostituto sicuro per shell, nessuna di queste shell differisce molto da Bash per quanto riguarda il difetto intrinseco di cui stai discutendo.

Un linguaggio come il Perl gestisce gli input in modo più sicuro. Ma la manutenibilità è anche la chiave qui. La sostituzione della shell Perl non è stata adottata molto bene. È responsabilità del manutentore della shell gestire gli input in modo sicuro. Quindi quando scrivi script, convalidi, convalidi, convalidi tutto! Usa i contratti di codice per assicurare sempre risultati corretti!

Perl Shell

Dichiarazione FSF su Shell Shock


Se è davvero il caso che altre shell abbiano lo stesso difetto - di cui dubito in qualche modo, in base alla discussione che ho visto - allora questo è un problema ENORME , perché molti programmi di terze parti passano variabili alla shell senza alcun tipo di convalida o altro. In tal caso, potremmo anche eliminare completamente POSIX.
DanL4096,

1
Il progetto Bash ha avuto 1 exploit di 0 giorni in 10 anni. Microsoft Windows ha oltre 10 exploit, tutti 0 giorni, a settimana. Sai anche quante persone hanno infastidito il team di sviluppo di Bash al riguardo? Basta aggiornarlo e andare avanti! Non è niente di grave.
Tyler Maginnis,

1
@ DanL4096. Passare le variabili agli script di shell che quindi non eseguono un controllo di integrità sufficiente sulle variabili non è un motivo per lanciare POSIX. Il problema risiede innanzitutto nella persona che ha scritto lo script della shell.
fpmurphy

0

Una funzionalità non abilitata per impostazione predefinita in mkshè cronologia shell.

  • Nel tuo .mkshrcset:

    export HISTFILE=~/.mksh-history

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.