¿Dónde son zsh y mksh incompatibles con bash?

11

¿Hasta qué punto pueden funcionar otros shells compatibles con POSIX como reemplazos razonables para bash? No necesitan ser verdaderos reemplazos "directos", pero lo suficientemente cerca como para funcionar con la mayoría de los scripts y admitir el resto con alguna modificación.

  1. Quiero tener scripts de bash explícitos (initscripts, scripts de cliente DHCP, etc.) que funcionen con una modificación mínima

  2. Quiero que mi propia colección de scripts de shell más especializados no necesite demasiada modificación

  3. Quiero tener características como la manipulación de cadenas y la coincidencia de patrones de expresiones regulares incorporadas

Los únicos contendientes serios que conozco son zsh y mksh. Entonces, para aquellos de ustedes aquí que son buenos con uno o ambos:

  1. ¿Qué características tiene bash que zsh y mksh respectivamente no tienen?

  2. ¿Qué características comparten los shells con bash, pero usan una sintaxis incompatible?

DanL4096
fuente
3
Comparación de shells de comandos: ( en.wikipedia.org/wiki/Comparison_of_command_shells ) Guía avanzada para la creación de scripts de bash: ( tldp.org/LDP/abs/html ) Manual ZSH: ( zsh.sourceforge.net/Guide/zshguide.html ) MirBSD Manual de Shell: ( mirbsd.org/htman/i386/man1/mksh.htm ). Lo siento, pero esta pregunta es demasiado compleja. ¿Tal vez debería preguntarse cómo parchear bash para corregir la vulnerabilidad dentro de su distribución específica de Linux?
Tyler Maginnis
3
No hay un shell que pueda funcionar como una caída en el reemplazo de bash, mksh y zsh puede funcionar como /bin/shcon varios niveles de corrección, pero no bash.
llua
1
Todo el asunto del shellshock parece no tener nada que ver con la pregunta central y solo distrae a la gente, así que lo
eliminé
3
Toda la pregunta es demasiado amplia. Quizás deberías eliminarlo.
Tyler Maginnis
1
La única preocupación que realmente tengo es que BASH está bien mantenido por la Free Software Foundation (FSF). Mis contactos allí me dicen que la revelación de la "falla fundamental" dentro de BASH solo conducirá a una implementación más fuerte y segura. Hay tantos shells alternativos que incluso comenzando a recomendar uno para sus requisitos, requeriría una comprensión sólida de su caso de uso. Luego, en el lado de O / S ... Tantas cosas están vinculadas a Bash que puede terminar reescribiendo todas sus llamadas de O / S a BASH. La mejor solución que puedo ver es elegir una distribución con un shell alternativo mantenido.
Tyler Maginnis

Respuestas:

19

Me atendré a las funciones de secuencias de comandos. Las características interactivas ricas (edición de línea de comandos, finalización, indicaciones, etc.) tienden a ser muy diferentes, logrando efectos similares de maneras totalmente incompatibles. ¿Qué características están en zsh y faltan en bash, o viceversa? da algunos consejos sobre el uso interactivo.

Lo más parecido a bash sería ATT ksh93 o mksh (el shell Korn y un clon). Zsh también tiene un subconjunto de características, pero necesitaría ejecutarlo en modo de emulación ksh, no en modo nativo de zsh.

No enumeraré las características de POSIX (que están disponibles en cualquier shshell moderno ), ni las características relativamente oscuras, ni las características mencionadas anteriormente para uso interactivo. Las observaciones son válidas a partir de bash 4.2, ksh 93u y mksh 40.9.20120630 como se encuentra en Debian wheezy.

Sintaxis de Shell

Citando

$'…'(cadenas literales con interpolación de barra invertida) está disponible en ksh93 y mksh. `$" ... "(cadenas traducidas) es específico de bash.

Construcciones condicionales

Mksh y ksh93 tienen que fallar ;&en una casedeclaración, pero no ;;&para probar casos posteriores. Mksh tiene ;|para eso, y mksh reciente permite ;;&compatibilidad.

((…))Las expresiones y [[ … ]]pruebas aritméticas son características de ksh. Algunos operadores condicionales son diferentes, consulte "expresiones condicionales" a continuación.

Coprocesos

Ksh y bash tienen coprocesos pero funcionan de manera diferente.

Las funciones

Mksh y ksh93 admiten la function name {…}sintaxis de las definiciones de funciones además del estándar name () {…}, pero el uso functionde ksh cambia las reglas de alcance, por lo que name () …debe mantener la compatibilidad. Las reglas para los caracteres permitidos en los nombres de funciones varían; atenerse a los caracteres alfanuméricos y _.

Expansión de la llave

Ksh93 y mksh admiten la expansión de llaves {foo,bar}. Ksh93 admite rangos numéricos {1..42}pero mksh no.

Expansión de parámetros

Ksh93 y apoyo extracción mksh subcadena con ${VAR:offset}y ${VAR:offset:length}, pero no como el caso plegable ${VAR^}, ${VAR,}, etc Usted puede hacer la conversión caso typeset -ly typeset -utanto en bash y ksh.

Admiten el reemplazo con ${VAR/PATTERN/STRING}o ${VAR/PATTERN//STRING}. Las reglas de comillas para STRING son ligeramente diferentes, por lo tanto, evite las barras invertidas (y tal vez otros caracteres) en STRING (cree una variable y ${VAR/PATTERN/$REPLACEMENT}úsela si el reemplazo contiene caracteres de comillas).

Expansión Array ( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]}) de trabajo en bash como en ksh.

${!VAR}expandiéndose a ${OTHERVAR}cuando el valor de VARis OTHERVAR(referencia de variable indirecta) es específico de bash (ksh hace algo diferente con ${!VAR}). Para obtener esta doble expansión en ksh, debe usar una referencia de nombre en su lugar ( typeset -n VAR=OTHERVAR; echo "$VAR"). ${!PREFIX*}funciona igual

Proceso de sustitución

Proceso de sustitución <(…)y >(…)se admite en ksh93 pero no en mksh.

Patrones comodín

Los patrones de globo extendido ksh que deben shopt -s extglobactivarse en bash siempre están disponibles en ksh93 y mksh.

Mksh no admite clases de personajes como [[:alpha:]].

Redirección de IO

Bash y ksh93 definen pseudo-archivos y , pero mksh no./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

La expansión de comodines en una redirección en los scripts (como por var="*.txt"; echo hello >$aescrito a.txtsi ese nombre de archivo es la única coincidencia para el patrón) es una característica específica de bash (otros shells nunca lo hacen en scripts).

<<< Las cadenas aquí funcionan en ksh como en bash.

El acceso directo >&para redirigir errores de sintaxis también es compatible con mksh pero no con ksh93.

Expresiones condicionales

[[ … ]] sintaxis de doble soporte

La sintaxis de doble parche de ksh es compatible con ATT ksh93 y mksh como en bash.

Operadores de archivos

Ksh93, mksh y bash admiten las mismas extensiones de POSIX, incluso -acomo sinónimo obsoleto de -e, -k(adhesivo), -G(propiedad de egid), -O(propietario de euid), -ef(mismo archivo), -nt(más nuevo que), -ot(más antiguo que).

-N FILE (modificado desde la última lectura) no es compatible con mksh.

Mksh no tiene un operador de coincidencia de expresiones regulares =~. Ksh93 tiene este operador, y realiza la misma coincidencia que en bash, pero no tiene el equivalente de BASH_REMATCHrecuperar grupos coincidentes después.

Operadores de cadenas

Ksh93 y mksh admiten los mismos operadores de comparación de cadenas <y >bash, así como el ==sinónimo de =. Mksh no utiliza la configuración regional para determinar el orden lexicográfico, compara cadenas como cadenas de bytes.

Otros operadores

-v VARpara probar si una variable está definida es específica de bash. En cualquier shell POSIX, puede usar [ -z "${VAR+1}" ].

Builtins

alias

El conjunto de caracteres permitidos en los nombres de alias no es el mismo en todos los shells. Creo que es lo mismo que para las funciones (ver arriba).

builtin

Ksh93 tiene una llamada incorporada builtin, pero no ejecuta un nombre como un comando incorporado. Se usa commandpara omitir alias y funciones; Esto llamará a un incorporado si existe, de lo contrario, un comando externo (puede evitar esto con PATH= command error_out_if_this_is_not_a_builtin).

caller

Esto es específico de bash. Usted puede obtener un efecto similar con .sh.fun, .sh.filey .sh.linenoen ksh93. En mksh hay al fin LINENO.

declare` local`typeset

declarees un nombre específico de bash para ksh's typeset. Uso typeset: también funciona en bash.

Mksh define localcomo un alias para typeset. En ksh93, debe usar typeset(o definir un alias).

Mksh no tiene matrices asociativas (están programadas para una versión aún no publicada).

No creo que haya un equivalente exacto de bash typeset -t(función de rastreo) en ksh.

cd

Ksh93 no tiene -e.

echo

Ksh93 y mksh procesan las opciones -ey -ncomo en bash. Mksh también entiende -E, ksh93 no lo trata como una opción. La expansión de barra invertida está desactivada de forma predeterminada en ksh93, activada de forma predeterminada en mksh.

enable

Ksh no proporciona una forma de deshabilitar los comandos incorporados. Para evitar una construcción, busque la ruta del comando externo e invoque explícitamente.

exec

Ksh93 tiene -apero no -l. Mksh no tiene ninguno.

export

Ni ksh93 ni mksh lo han hecho export -n. Use en su typeset +x foolugar, funciona en bash y ksh.

Ksh no exporta funciones a través del entorno.

let

let es lo mismo en bash y ksh.

mapfile, readarray

Esta es una característica específica de bash. Puede usar while readbucles o sustitución de comandos para leer un archivo y dividirlo en una matriz de líneas. Cuida IFSy pega. Aquí está el equivalente de mapfile -t lines </path/to/file:

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

printf

printfEs muy similar. Creo que ksh93 es compatible con todas las directivas de formato de bash. mksh no es compatible con %qo %(DATE_FORMAT)T; en algunas instalaciones, printfno es un mksh incorporado y llama al comando externo en su lugar.

printf -v VAR es específico de bash, ksh siempre imprime en salida estándar.

read

Varias opciones son específicas de bash, incluidas todas las de readline. Las opciones -r, -d, -n, -N, -t, -uson idénticos en bash, ksh93 y mksh.

readonly

Puede declarar una variable como de solo lectura en Ksh93 y mksh con la misma sintaxis. Si la variable es una matriz, primero debe asignarla y luego hacerla de solo lectura con readonly VAR. Las funciones no se pueden hacer de solo lectura en ksh.

set, shopt

Todas las opciones sety set -oson características de POSIX o ksh.

shoptes específico de bash. Muchas opciones se refieren al uso interactivo de todos modos. Para conocer los efectos sobre el globbing y otras funciones habilitadas por algunas opciones, consulte la sección "Opciones" a continuación.

source

Esta variante de .existe en ksh también. En bash y mksh, sourcebusca el directorio actual después PATH, pero en ksh93, es un equivalente exacto de ..

trap

La DEBUGpseudo-señal no se implementa en mksh. En ksh93, existe con una forma diferente de informar información, consulte el manual para más detalles.

type

En ksh, typees un alias para whence -v. En mksh, type -pno imprime la ruta al ejecutable, sino un mensaje legible por humanos; necesitas usar whence -p COMMANDen su lugar.

Opciones

shopt -s dotglob - no ignore los archivos de puntos en globbing

Para emular la dotglobopción en ksh93, puede configurar FIGNORE='@(.|..)'. No creo que haya algo así en mksh.

shopt -s extglob - patrones de globo extendido ksh

La extglobopción siempre está activada en ksh.

shopt -s failglob - error si un patrón global no coincide con nada

No creo que esto exista ni en mksh ni en ksh93. Lo hace en zsh (comportamiento por defecto a menos que null_globo csh_null_globson set).

shopt -s globstar**/globo recursivo

Ksh93 tiene globbing recursivo con **/, habilitado con set -G. Mksh no tiene globulación recursiva.

shopt -s lastpipe - ejecuta el último comando de una tubería en el shell principal

Ksh93 siempre ejecuta el último comando de una tubería en el shell principal, que en bash requiere lastpipeque se establezca la opción. Mksh siempre ejecuta el último comando de una tubería en una subshell.

shopt -s nocaseglob, shopt -s nocasematch- patrones que no distinguen entre mayúsculas y minúsculas

Mksh no tiene coincidencia de patrones sin distinción entre mayúsculas y minúsculas. Ksh93 lo admite patrón por patrón: prefije el patrón con ~(i).

shopt -s nullglob - expande patrones que no coinciden con ningún archivo a una lista vacía

Mksh no tiene esto. Ksh93 lo admite patrón por patrón: prefije el patrón con ~(N).

Variables

Obviamente, la mayoría de las BASH_xxxvariables no existen en ksh. $BASHPIDse puede emular con el costoso pero portátil sh -c 'echo $PPID', y se ha agregado recientemente a mksh. BASH_LINEestá .sh.linenoen ksh93 y LINENOen mksh. BASH_SUBSHELLestá .sh.subshellen ksh93.

Mksh y ksh93 obtienen el archivo proporcionado ENVcuando se inician.

EUIDy UIDno existen en ksh93. Mksh los llama USER_IDy KSH_UID; que no tiene GROUPS.

FUNCNAMEy FUNCNESTno existen en ksh. Ksh93 tiene .sh.funy .sh.level. Las funciones declaradas con function foo { …; }(¡sin paréntesis!) Tienen su propio nombre $0.

GLOBIGNOREexiste en ksh93 pero con un nombre y una sintaxis diferentes: se llama FIGNOREy es un patrón único, no una lista separada por dos puntos. Usa un @(…|…)patrón. Ksh FIGNOREsubsume bash, con una sintaxis completamente diferente.

Ksh93 y mksh no tienen nada como HOSTTYPE, MACHTYPEy OSTYPE. Ni SHELLOPTSo TIMEFORMAT.

Mksh sí PIPESTATUS, pero ksh93 no.

Mksh y ksh93 tienen RANDOM.

Gilles 'SO- deja de ser malvado'
fuente
si no desea reproducir la marca comercial (no registrada) "mksh" correctamente al comienzo de una oración ( vea también "" dd "" vs. "" dd "" aquí ), escriba "The MirBSD" Korn Shell "en su lugar. Siempre es incorrecto poner en mayúscula cualquier letra de "mksh". Gracias.
mirabilos
¿Cómo se $BASHPIDpuede emular con sh -c 'echo $PPID'? Lo intenté (sh -c 'echo $PPID')en Bash pero me da el mismo PID que $$.
Franklin Yu
Creo que la pregunta encaja mejor aquí . Copié la pregunta allí.
Franklin Yu
4

Esta pregunta es bastante amplia.

Tanto mksh como zsh son shells que admiten muchas extensiones específicas de bash de GNU , pero siempre hay algunas que no se entienden.

zsh admite más cosas, pero solo en su modo zsh nativo, que no es compatible con shells POSIX (como GNU bash, AT&T ksh93 , mksh). Además, mksh es mucho más delgado, más rápido y más portátil.

En general, si se trata de sus guiones que estamos hablando, seguir adelante, simplemente probarlos. (mksh todavía no admite matrices asociativas de estilo bash4. El comando "declare" es específico de bash, "typeset" es un equivalente. No estoy lo suficientemente familiarizado con zsh como para decir algo sobre eso directamente. ksh93 no tiene "local" pero también usa "typeset" para eso.) Pero si se trata, por ejemplo, de ejecutar un sistema Debian sin bash, olvídalo. La existencia de bash es parte de la "promesa" (API / ABI del sistema), y depende mucho de ella.

Descargo de responsabilidad: soy el desarrollador de mksh.

mirabilos
fuente
1

ZSH Comparación de proyectiles

Sin embargo, en los últimos años ha habido una cierta cantidad de cruces en las extensiones. Zsh (a partir de 3.1.6) tiene bash ${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} 'y ${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} 'donde old comienza 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)' para que coincida con el inicio de una cadena , y `(#e) 'para que coincida con el final. Estos requieren que se configure la opción EXTENDED_GLOB.

No estoy familiarizado con mksh, así que no sé dónde buscar esa respuesta.

Si está buscando un reemplazo seguro para el shell, ninguno de estos shells difiere mucho de Bash en cuanto a la falla inherente que está discutiendo.

Un lenguaje como Perl maneja las entradas de manera más segura. Pero la mantenibilidad también es clave aquí. El reemplazo de shell Perl no está muy bien adoptado. Es responsabilidad del mantenedor de shell manejar las entradas de forma segura. Entonces, cuando escribes scripts, ¡ valida, valida, valida todo! ¡Use contratos de código para asegurar resultados correctos cada vez!

Perl Shell

Declaración de la FSF sobre el impacto de Shell

Tyler Maginnis
fuente
Si realmente es el caso de que otros shells tengan el mismo defecto, lo cual dudo un poco, según la discusión que he visto, entonces ese es un problema ENORME , porque muchos programas de terceros pasan variables al shell sin ningún tipo de validación o cualquier cosa. Si ese es el caso, también podríamos descartar POSIX por completo.
DanL4096
1
El proyecto Bash ha tenido una explotación de 0 días en 10 años. Microsoft Windows tiene más de 10 exploits, todos los 0 días, por semana. ¿Sabes cuántas personas han molestado al equipo de desarrollo de Bash sobre esto? ¡Solo actualízalo y sigue adelante! No es la gran cosa.
Tyler Maginnis
1
@ DanL4096. Pasar variables a scripts de shell que luego no realizan una comprobación de sanidad suficiente en las variables no es motivo para descartar POSIX. El problema radica en la persona que escribió el script de shell en primer lugar.
fpmurphy
0

Una característica no habilitada por defecto en el mkshhistorial de shell.

  • En su .mkshrcconjunto justo:

    export HISTFILE=~/.mksh-history

Stuart Cardall
fuente