Por segurança, eu gostaria que o bash abortasse a execução de um script se ele encontrar um erro de sintaxe.
Para minha surpresa, não posso conseguir isso. ( set -e
não é suficiente.) Exemplo:
#!/bin/bash
# Do exit on any error:
set -e
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Resultado (bash-3.2.39 ou bash-3.2.51):
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Bem, não podemos verificar $?
após cada instrução para detectar erros de sintaxe.
(Eu esperava um comportamento tão seguro de uma linguagem de programação sensata ... talvez isso deva ser relatado como um bug / desejo para atacar os desenvolvedores)
Mais experiências
if
Não faz diferença.
Removendo if
:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Resultado:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Talvez esteja relacionado ao exercício 2 de http://mywiki.wooledge.org/BashFAQ/105 e tenha algo a ver com isso (( ))
. Mas acho que ainda não é razoável continuar executando após um erro de sintaxe.
Não, (( ))
não faz diferença!
Comporta-se mal, mesmo sem o teste aritmético! Apenas um script simples e básico:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Resultado:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
fonte
set -e
não é suficiente porque seu erro de sintaxe está em umaif
instrução Em qualquer outro lugar deve abortar o script.set -e
não funcionou. Mas minha pergunta ainda faz sentido. É possível cancelar qualquer erro de sintaxe?Respostas:
Agrupar o todo em uma função parece fazer o truque:
Resultado:
Embora eu não tenha idéia do porquê - talvez alguém possa explicar?
fonte
echo 'Bad2: has not aborted the execution after bad main!'
como o último ao seu exemplo e a saída é: $ LC_ALL = C ./sh-on-syntax-err ./sh-on-syntax-err: linha 6: #: erro de sintaxe: operando esperado ( token de erro é "#") Bad2: não interrompeu a execução após main ruim! $Você provavelmente está enganado sobre o significado genuíno de
set -e
. Uma leitura cuidadosa da saída doshelp set
shows:O mesmo
-e
ocorre com o status de saída de comandos que é diferente de zero, não com erros de sintaxe no seu script.Em geral, é considerado uma má prática usar
set -e
, porque todos os erros (ou seja, todos os retornos diferentes de zero) devem ser manipulados de maneira inteligente pelo script (pense em um script robusto, não nos que ficam loucos depois de inserir um nome de arquivo com um espaço ou que começa com um hypen).Dependendo do tipo de erro de sintaxe, o script pode nem mesmo ser executado. Não tenho conhecimento suficiente do bash para dizer exatamente que classe de erros de sintaxe (se eles podem ser classificados) pode levar a um aborto imediato do script ou não. Talvez alguns gurus do Bash participem e esclareçam tudo.
Só espero esclarecer a
set -e
afirmação!Sobre o seu desejo:
A resposta é definitivamente não! como o que você observou (
set -e
sem responder como você espera) está de fato muito bem documentado.fonte
set -e
- é apenas um pouco perto dos meus objetivos, é por isso que é mencionado e usado aqui. Minha pergunta não é sobreset -e
, é sobre a insegurança do bash, se não for possível abortar com erros de sintaxe. Estou procurando uma maneira de fazê-lo sempre abortar com erros de sintaxe.Você pode fazer o script verificar-se colocando algo como
próximo ao topo do script - depois,
set -e
mas antes, de qualquer parte significativa do código.Devo dizer que isso não parece muito robusto, mas se funcionar para você, talvez seja aceitável.
fonte
set -e
:bash -n "$0" || exit
Primeiro, o
(( ))
in bash é usado como cálculos aritméticos, para não usar no if ... use o[]
para isso.Segundo, o
${a[#]}
é estranho e é por isso que está dando erros ... o#
não tem nenhum significado de matrizEu não sei o que você quer fazer com isso, mas eu suponho que você quer saber o número de campos, assim que você quer
${#a[*]}
, em vezFinalmente, ao comparar números inteiros,
-eq
recomenda-se over==
(usado para strings). o==
também funcionará, mas-eq
é recomendado.então você quer:
fonte
((
palavra-chave com aif
palavra - chave. Por exemploif (( 5 * $b > 53 ))
,. A menos que você está apontando para portabilidade com conchas mais velhos,[[
é geralmente preferível ao longo[
.[[
e((
foram projetados especificamente como testes leves para serem usados com "se" etc. - ao contrário[
, eles nunca geram um subprocesso para avaliar a condição.[
é um bash embutido. Os reservatórios mais antigos esperam que seja seu próprio programa.