Onde o zsh e o mksh são incompatíveis com o bash?

11

Até que ponto outros shells compatíveis com POSIX podem funcionar como substitutos razoáveis ​​para o bash? Eles não precisam ser substituições verdadeiras, mas são suficientemente próximos para trabalhar com a maioria dos scripts e dar suporte ao restante com algumas modificações.

  1. Desejo que scripts bash explícitos - initscripts, scripts de cliente DHCP, etc. - funcionem com modificações mínimas

  2. Quero que minha própria coleção de scripts shell mais especializados não precise de muita modificação

  3. Eu quero ter recursos como manipulação de string e correspondência de padrão regex interna

Os únicos candidatos sérios que eu conheço são zsh e mksh. Então, para aqueles de vocês aqui que são bons com um ou com os dois:

  1. Quais recursos o bash tem que zsh e mksh, respectivamente, não têm?

  2. Para quais recursos os shells compartilham com o bash, mas usam sintaxe incompatível?

DanL4096
fonte
3
Comparação de shells de comando: ( pt.wikipedia.org/wiki/Comparison_of_command_shells ) Guia avançado para scripts Bash: ( tldp.org/LDP/abs/html ) Manual do ZSH: ( zsh.sourceforge.net/Guide/zshguide.html ) MirBSD Manual do Shell: ( mirbsd.org/htman/i386/man1/mksh.htm ). Sinto muito, mas esta pergunta é muito complexa. Talvez você deva estar perguntando como corrigir o bash para corrigir a vulnerabilidade da sua distribuição específica do Linux?
Tyler Maginnis
3
Não existe um shell que possa funcionar como uma queda na substituição de bash, mksh e zsh pode funcionar como /bin/shem vários níveis de correção, mas não bash.
Octua
1
A coisa toda shellshock parece não ter nada a ver com a questão central e está apenas distrair as pessoas, por isso eu o retirei
Michael Mrozek
3
A questão toda é excessivamente ampla. Talvez você deva removê-lo.
Tyler Maginnis
1
A única preocupação que realmente tenho é que o BASH é bem mantido pela Free Software Foundation (FSF). Meus contatos me dizem que a revelação da "falha fundamental" no BASH só levará a uma implementação mais forte e segura. Existem tantos shells alternativos que, mesmo começando a recomendar um para seus requisitos, eu exigiria uma sólida compreensão do seu caso de uso. Depois, no lado O / S ... Tantas coisas estão ligadas ao Bash que você pode reescrever todas as suas chamadas de O / S no BASH. A melhor solução que posso ver é escolher uma distribuição com um alt-shell mantido.
Tyler Maginnis

Respostas:

19

Vou me ater aos recursos de script. Recursos interativos avançados (edição de linha de comando, conclusão, prompts etc.) tendem a ser muito diferentes, atingindo efeitos semelhantes de maneiras totalmente incompatíveis. Quais recursos estão no zsh e estão ausentes no bash ou vice-versa? fornece algumas dicas sobre o uso interativo.

A coisa mais próxima do bash seria ATT ksh93 ou mksh (o shell Korn e um clone). O Zsh também possui um subconjunto de recursos, mas você precisará executá-lo no modo de emulação ksh, não no modo nativo do zsh.

Não listarei os recursos do POSIX (disponíveis em qualquer shshell moderno ), nem os recursos relativamente obscuros, nem os mencionados acima, para uso interativo. As observações são válidas a partir do bash 4.2, ksh 93u e mksh 40.9.20120630, conforme encontrado no Debian wheezy.

Sintaxe do shell

Citação

$'…'(cadeias literais com interpolação de barra invertida) está disponível em ksh93 e mksh. `$" ... "(cadeias traduzidas) é específico do bash.

Construções condicionais

Mksh e ksh93 precisam ;&passar por uma casedeclaração, mas não ;;&para testar casos subseqüentes. Mksh tem ;|isso, e mksh recente permite ;;&compatibilidade.

((…))expressões e [[ … ]]testes aritméticos são recursos do ksh. Alguns operadores condicionais são diferentes, consulte "expressões condicionais" abaixo.

Coprocesses

Ksh e bash têm coprocessos, mas funcionam de maneira diferente.

Funções

Mksh e ksh93 suportam a function name {…}sintaxe das definições de funções além do padrão name () {…}, mas usando as functionregras de escopo das mudanças no ksh, portanto, mantenha a name () …compatibilidade. As regras para caracteres permitidos nos nomes das funções variam; atenha-se a alfanuméricos e _.

Expansão de cinta

Ksh93 e mksh suportam expansão de chaves {foo,bar}. O Ksh93 suporta intervalos numéricos, {1..42}mas o mksh não.

Expansão de parâmetros

Ksh93 e extração mksh apoio substring com ${VAR:offset}e ${VAR:offset:length}, mas não caso dobrar como ${VAR^}, ${VAR,}, etc. Você pode fazer a conversão caso typeset -le typeset -uem ambos bash e ksh.

Eles suportam a substituição com ${VAR/PATTERN/STRING}ou ${VAR/PATTERN//STRING}. As regras de citação para STRING são um pouco diferentes, portanto, evite barras invertidas (e talvez outros caracteres) em STRING (crie uma variável e use-a ${VAR/PATTERN/$REPLACEMENT}se a substituição contiver caracteres de citação).

Expansão Array ( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]}) o trabalho em bash como em ksh.

${!VAR}expandindo para ${OTHERVAR}quando o valor de VARé OTHERVAR(referência variável indireta) é específico do bash (o ksh faz algo diferente com ${!VAR}). Para obter essa dupla expansão no ksh, você precisa usar uma referência de nome ( typeset -n VAR=OTHERVAR; echo "$VAR"). ${!PREFIX*}funciona da mesma maneira.

Substituição de processo

Substituição de processo <(…)e >(…)é suportado no ksh93, mas não no mksh.

Padrões curinga

Os padrões glob estendidos do ksh que precisam shopt -s extglobser ativados no bash estão sempre disponíveis no ksh93 e no mksh.

Mksh não suporta classes de personagens como [[:alpha:]].

Redirecionamento de E / S

Bash e ksh93 definem pseudo-arquivos e , mas mksh não./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

A expansão de curingas em um redirecionamento em scripts (como por var="*.txt"; echo hello >$aescrito, para a.txtse esse nome de arquivo for a única correspondência para o padrão) é um recurso específico do bash (outros shells nunca fazem isso em scripts).

<<< as strings here funcionam no ksh como no bash.

O atalho >&para redirecionar erros de sintaxe também é suportado pelo mksh, mas não pelo ksh93.

Expressões condicionais

[[ … ]] sintaxe de colchete duplo

A sintaxe de colchete duplo do ksh é suportada pelo ATT ksh93 e pelo mksh como no bash.

Operadores de arquivo

Ksh93, mksh e suporte do bash as mesmas extensões para POSIX, incluindo -acomo um sinônimo obsoleta de -e, -k(pegajosa), -G(propriedade da egid), -O(proprietário por euid), -ef(mesmo arquivo), -nt(mais recente do que), -ot(acima de).

-N FILE (modificado desde a última leitura) não é suportado pelo mksh.

Mksh não tem um operador de correspondência de regexp =~. O Ksh93 possui esse operador e executa a mesma correspondência que no bash, mas não tem o equivalente BASH_REMATCHa recuperar grupos correspondidos posteriormente.

Operadores de string

Ksh93 e mksh suportam os mesmos operadores de comparação de cadeias <e >bash, além do ==sinônimo =. Mksh não usa configurações de localidade para determinar a ordem lexicográfica, ele compara cadeias como cadeias de bytes.

Outros operadores

-v VARpara testar se uma variável está definida é específico do bash. Em qualquer shell POSIX, você pode usar [ -z "${VAR+1}" ].

Builtins

alias

O conjunto de caracteres permitidos nos nomes alternativos não é o mesmo em todos os shells. Eu acho que é o mesmo que para funções (veja acima).

builtin

O Ksh93 possui um builtinbuilt-in chamado , mas não executa um nome como um comando interno . Use commandpara ignorar aliases e funções; isso chamará um builtin, se houver, caso contrário, um comando externo (você pode evitar isso com PATH= command error_out_if_this_is_not_a_builtin).

caller

Isso é específico do bash. Você pode obter um efeito semelhante com .sh.fun, .sh.filee .sh.linenono ksh93. Em mksh, finalmente LINENO.

declare, local,typeset

declareé um nome específico do bash para ksh's typeset. Uso typeset: ele também funciona no bash.

Mksh define localcomo um alias para typeset. No ksh93, você precisa usar typeset(ou definir um alias).

Mksh não possui matrizes associativas (elas estão previstas para uma versão ainda não lançada).

Eu não acho que exista um equivalente exato do bash typeset -t(função trace) no ksh.

cd

Ksh93 não tem -e.

echo

Ksh93 e mksh processam as opções -ee -ncomo no bash. Mksh também entende -E, o ksh93 não o trata como uma opção. A expansão da barra invertida está desativada por padrão em ksh93, ativada por padrão em mksh.

enable

O Ksh não fornece uma maneira de desativar os comandos internos. Para evitar um builtin, procure o caminho do comando externo e chame-o explicitamente.

exec

Ksh93 tem -amas não -l. Mksh não tem nenhum.

export

Nem ksh93 nem mksh tem export -n. Em typeset +x foovez disso, use em bash e ksh.

O Ksh não exporta funções através do ambiente.

let

let é o mesmo no bash e no ksh.

mapfile, readarray

Este é um recurso específico do bash. Você pode usar while readloops ou substituição de comando para ler um arquivo e dividi-lo em uma matriz de linhas. Cuide IFSe globbing. Aqui está o equivalente a mapfile -t lines </path/to/file:

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

printf

printfé muito parecido. Eu acho que o ksh93 suporta todas as diretivas de formato do bash. mksh não suporta %qou %(DATE_FORMAT)T; em algumas instalações, printfnão é um mksh embutido e chama o comando externo.

printf -v VAR é específico do bash, o ksh sempre imprime na saída padrão.

read

Várias opções são específicas do bash, incluindo todas sobre o readline. As opções -r, -d, -n, -N, -t, -usão idênticos em bash, ksh93 e mksh.

readonly

Você pode declarar uma variável como somente leitura no Ksh93 e mksh com a mesma sintaxe. Se a variável for uma matriz, você precisará atribuir a ela primeiro e depois torná-la somente leitura com readonly VAR. As funções não podem ser feitas somente leitura em ksh.

set, shopt

Todas as opções para sete set -osão recursos POSIX ou ksh.

shopté específico do bash. Muitas opções dizem respeito ao uso interativo de qualquer maneira. Para efeitos sobre globos e outros recursos ativados por algumas opções, consulte a seção “Opções” abaixo.

source

Esta variante de .existe também no ksh. No bash e mksh, sourcepesquisa o diretório atual depois PATH, mas no ksh93, é um equivalente exato de ..

trap

O DEBUGpseudo-sinal não é implementado no mksh. No ksh93, ele existe com uma maneira diferente de relatar informações, consulte o manual para obter detalhes.

type

No ksh, typeé um apelido para whence -v. No mksh, type -pnão imprime o caminho para o executável, mas uma mensagem legível por humanos; você precisa usar whence -p COMMANDem seu lugar.

Opções

shopt -s dotglob - não ignore arquivos de ponto no globbing

Para emular a dotglobopção no ksh93, você pode definir FIGNORE='@(.|..)'. Eu não acho que exista algo assim no mksh.

shopt -s extglob - padrões estendidos ksh de glob

A extglobopção está efetivamente sempre ativada em ksh.

shopt -s failglob - erro se um padrão glob não corresponder a nada

Eu não acho que isso exista no mksh ou no ksh93. Ele faz em zsh (comportamento padrão, a menos null_globou csh_null_globsão set).

shopt -s globstar**/globbing recursivo

O Ksh93 possui globbing recursivo com **/, ativado com set -G. Mksh não tem globbing recursivo.

shopt -s lastpipe - execute o último comando de um pipeline no shell pai

O Ksh93 sempre executa o último comando de um pipeline no shell pai, que no bash requer que a lastpipeopção seja definida. Mksh sempre executa o último comando de um pipeline em um subshell.

shopt -s nocaseglob, shopt -s nocasematch- padrões que não diferenciam maiúsculas de minúsculas

Mksh não possui correspondência de padrão que não diferencia maiúsculas de minúsculas. O Ksh93 o suporta padrão por padrão: prefixe o padrão com ~(i).

shopt -s nullglob - expanda padrões que não correspondem a nenhum arquivo para uma lista vazia

Mksh não tem isso. O Ksh93 o suporta padrão por padrão: prefixe o padrão com ~(N).

Variáveis

Obviamente, a maioria das BASH_xxxvariáveis ​​não existe no ksh. $BASHPIDpode ser emulado com o caro, mas portátil sh -c 'echo $PPID'e foi adicionado recentemente ao mksh. BASH_LINEestá .sh.linenoem ksh93 e LINENOem mksh. BASH_SUBSHELLestá .sh.subshellem ksh93.

Mksh e ksh93 fornecem o arquivo fornecido ENVquando são inicializados.

EUIDe UIDnão existe no ksh93. Mksh os chama USER_IDe KSH_UID; não tem GROUPS.

FUNCNAMEe FUNCNESTnão existe em ksh. Ksh93 tem .sh.fune .sh.level. As funções declaradas com function foo { …; }(sem parênteses!) Têm seu próprio nome $0.

GLOBIGNOREexiste no ksh93, mas com um nome e sintaxe diferentes: é chamado FIGNOREe é um padrão único, não uma lista separada por dois-pontos. Use um @(…|…)padrão. O Ksh substitui o FIGNOREbash's, com uma sintaxe totalmente diferente.

Ksh93 e mksh não têm nada como HOSTTYPE, MACHTYPEe OSTYPE. Nem SHELLOPTSou TIMEFORMAT.

Mksh tem PIPESTATUS, mas ksh93 não.

Mksh e ksh93 têm RANDOM.

Gilles 'SO- parar de ser mau'
fonte
se você não deseja reproduzir corretamente a marca comercial (não registrada) “mksh” no início de uma frase ( consulte também ““ dd. ”” vs. ““ dd ”.” aqui ), escreva “The MirBSD Korn Shell ”. É sempre errado colocar em maiúscula qualquer letra de "mksh". Obrigado.
mirabilos
Como pode $BASHPIDser emulado sh -c 'echo $PPID'? Eu tentei (sh -c 'echo $PPID')no Bash, mas ele me dá o mesmo PID que $$.
Franklin Yu
Eu acho que a pergunta se encaixa melhor aqui . Eu copiei a pergunta lá.
Franklin Yu
4

Esta questão é bastante ampla.

O mksh e o zsh são shells que suportam muitas extensões específicas do GNU bash , mas sempre existem algumas que não são compreendidas.

O zsh suporta mais coisas, mas apenas no modo zsh nativo, que não é compatível com os shells POSIX (como GNU bash, AT&T ksh93 , mksh). Além disso, o mksh é muito mais enxuto, rápido e portátil.

Em geral, se estamos falando de seus scripts, vá em frente, apenas teste-os. (mksh ainda não suporta matrizes associativas no estilo bash4. O comando "declarar" é específico do bash, "typeset" é equivalente. Não estou familiarizado o suficiente com zsh para afirmar nada sobre isso. ksh93 não tem "local" mas também usa "typeset" para isso.) Mas se isso é sobre, digamos, executar um sistema Debian sem falhas, esqueça-o. A existência do bash faz parte da "promessa" (API / ABI do sistema) e depende muito disso.

Disclaimer: Eu sou o desenvolvedor mksh.

mirabilos
fonte
1

Comparação ZSH de Cascas

Nos últimos anos, houve uma certa quantidade de crossover nas extensões, no entanto. O Zsh (a partir do 3.1.6) possui ${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} '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#' ou %' inside a parameter: in other words{var / $ old / new} ' do bash, onde old começa com um #' 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 coincidir com o início de uma string e `(#e) 'para corresponder ao final. Isso exige que a opção EXTENDED_GLOB seja configurada.

Não estou familiarizado com mksh, então não sei onde procurar por essa resposta.

Se você está procurando um substituto seguro para o shell, nenhum desses shells difere muito do Bash no que diz respeito à falha inerente que você está discutindo.

Uma linguagem como Perl lida com entradas com mais segurança. Mas a manutenção também é fundamental aqui. A substituição do shell Perl não é muito bem adotada. É responsabilidade do mantenedor do shell manipular as entradas com segurança. Então, quando você escreve scripts, valida, valida, valida tudo! Use contratos de código para garantir sempre resultados corretos!

Perl Shell

Declaração da FSF sobre o choque da Shell

Tyler Maginnis
fonte
Se é realmente o caso de outras conchas terem a mesma falha - o que duvido um pouco, com base na discussão que eu já vi -, esse é um problema ENORME , porque muitos programas de terceiros passam variáveis ​​para o shell sem nenhum tipo de validação ou qualquer coisa. Se for esse o caso, podemos também jogar fora o POSIX completamente.
precisa saber é o seguinte
1
O projeto Bash teve uma exploração de 0 dia em 10 anos. O Microsoft Windows possui mais de 10 explorações, todos os dias 0, por semana. Você sabe quantas pessoas incomodaram a equipe de desenvolvimento do Bash sobre isso? Basta atualizá-lo e seguir em frente! Não é grande coisa.
Tyler Maginnis #
1
@ DanL4096. Passar variáveis ​​para scripts de shell que, em seguida, não fazem verificação de integridade suficiente nas variáveis ​​não é motivo para jogar fora o POSIX. O problema está na pessoa que escreveu o shell script em primeiro lugar.
precisa saber é o seguinte
0

Um recurso não ativado por padrão mkshé o histórico do shell.

  • No seu .mkshrcconjunto definido:

    export HISTFILE=~/.mksh-history

Stuart Cardall
fonte