Como faço para verificar a sintaxe de um script Bash sem executá-lo?


Respostas:


380
bash -n scriptname

Talvez uma ressalva óbvia: isso valida a sintaxe, mas não verifica se o script bash tenta executar um comando que não está no seu caminho, como em ech hellovez de echo hello.


9
Na página de manual do bash, em "SHELL BUILTIN COMMANDS / set", -n está documentado e, como indica o início da página de manual, o bash interpreta todas as opções de caractere único set.
ephemient

24
para adicionar ao (para mim) ressalva não óbvio, ele também não vai pegar um erro causado por um espaço faltando if ["$var" == "string" ]em vez deif [ "$var" == "string" ]
Brynjar

11
@ Brynjar Isso porque é apenas uma verificação de sintaxe. O colchete aberto não é sintaxe, é o nome da função a ser executada. type [diz "[é um shell embutido". Em última análise, delega para o testprograma, mas espera também um colchete. Então é assim if test"$var", que não é o que o autor quis dizer, mas é sintaticamente válido (digamos que $ var tenha o valor "a", veremos "bash: testa: comando não encontrado"). O ponto é que, sintaticamente, não há espaço em falta.
Joshua Cheek

2
@ JoshuaCheek: Builtin [só é invocado neste caso se for $varexpandido para uma string vazia . Se for $varexpandido para uma sequência não vazia , [é concatenado com essa sequência e é interpretado como um nome de comando (não nome da função ) por Bash e, sim, isso é sintaticamente válido, mas, como você afirma, obviamente não é a intenção. Se você usar, em [[vez de [, mesmo que [[seja uma palavra-chave shell (em vez de incorporada), obterá o mesmo resultado, porque a concatenação não intencional de cadeias ainda substitui o reconhecimento da palavra-chave.
mklement0

2
@ JoshuaCheek: O Bash ainda está com a sintaxe - verificando aqui: está verificando a sintaxe da chamada de comando simples : ["$var"é sintaticamente uma expressão de nome de comando válida ; da mesma forma, tokens ==e "$string"são argumentos de comando válidos . (Geralmente, builtin [é analisado com comando sintaxe, enquanto que [[- como um shell de palavras-chave - é analisado de forma diferente.) O builtin shell [que não delegar ao " testprograma" (utilitário externo): bash, dash, ksh, zshtodos têm incorporado versões de ambos [etest, e eles não chamam suas contrapartes de utilidade externa.
mklement0

127

O tempo muda tudo. Aqui está um site que fornece verificação de sintaxe on-line para o shell script.

Eu achei muito poderoso detectar erros comuns.

insira a descrição da imagem aqui

Sobre o ShellCheck

O ShellCheck é uma ferramenta estática de análise e limpeza para scripts sh / bash. Ele se concentra principalmente no tratamento de erros e armadilhas típicas para iniciantes e de nível intermediário, em que o shell apenas fornece uma mensagem de erro enigmática ou comportamento estranho, mas também relata alguns problemas mais avançados em que casos de canto podem causar falhas atrasadas.

O código-fonte Haskell está disponível no GitHub!


5
Ótima dica; no OSX agora você pode também instalar o CLI shellcheck.net, shellcheck, via Homebrew : brew install shellcheck.
mklement0

3
Também no debian & friends:apt-get install shellcheck
that other guy

Para o Ubuntu confiável, este pacote deve ser instalado a partir trusty-backports.
Peterino 04/04/2015

Como mencionado acima, a dependência de confiança necessário, e pode instalá-lo como abaixo no Ubuntu 14.04: sudo apt-get -f install, então: sudo sudo apt-get install shellcheck
Zhihong

Isso é realmente útil, mas não usa o analisador do Bash, mas o seu próprio. Na maioria dos casos, isso é bom o suficiente e pode identificar problemas de análise e outros, mas há pelo menos um caso extremo (e provavelmente outros que eu não vi) em que ele não é analisado da mesma maneira.
Daniel H

38

Eu também habilito a opção 'u' em todos os scripts do bash que escrevo para fazer uma verificação extra:

set -u 

Isso relatará o uso de variáveis ​​não inicializadas, como no script a seguir 'check_init.sh'

#!/bin/sh
set -u
message=hello
echo $mesage

Executando o script:

$ check_init.sh

Relatará o seguinte:

./check_init.sh[4]: mesage: Parâmetro não definido.

Muito útil para detectar erros de digitação


4
i definir essas bandeiras sempre em meus scripts bash, se ele passar estes, é bom para ir "set -o errexit" "set -o nounset" "set -o pipefail"
μολὼν.λαβέ

+1 porque, set -uembora isso realmente não responda à pergunta, você deve executar o script para receber a mensagem de erro. Nem mesmo bash -n check_init.shmostra que aviso
rubo77

23
sh  -n   script-name 

Rode isto. Se houver algum erro de sintaxe no script, ele retornará a mesma mensagem de erro. Se não houver erros, ele será exibido sem enviar nenhuma mensagem. Você pode verificar imediatamente usando echo $?, que retornará 0confirmando com êxito sem nenhum erro.

Funcionou bem para mim. Eu corri no Linux OS, Bash Shell.


1
Embora não exatamente relacionada à verificação de sintaxe Bash - usando -x set e set + x para depurar o script completo ou seções do script é bastante útil
gurum

Obrigado por isso não sabia não sabia sobre o -n, mas o que eu queria era @GuruM> sh -x test.sh como que exibe a saída gerada do script
ZZAPPER

1
Sim. Esqueci de mencionar que você pode fazer o seguinte Na linha de comando: 1) bash -x test.sh #Este executa todo o script no 'modo de depuração' 2) set + x; bash test.sh; set -x #set modo de depuração ativado / desativado antes / depois da execução do script No script: a) #! / bin / bash -x #add 'modo de depuração' na parte superior do script b) set + x; código; set -x #Adicione 'debug mode' em qualquer secção do roteiro
gurum

sh -nprovavelmente não verificará se o script é um script Bash válido. Pode dar falsos negativos. shé uma variante de shell Bourne que geralmente não é o Bash. Por exemplo, no Ubuntu Linux realpath -e $(command -v sh)dá / bin / dash
jarno

4

Na verdade, verifico todos os scripts bash no diretório atual para erros de sintaxe SEM executá-los usando a findferramenta:

Exemplo:

find . -name '*.sh' -exec bash -n {} \;

Se você quiser usá-lo para um único arquivo, basta editar o curinga com o nome do arquivo.


3

comando nulo [dois pontos] também é útil ao depurar para ver o valor da variável

set -x
for i in {1..10}; do
    let i=i+1
    : i=$i
done
set - 

ele usa expansões de parâmetro
mug896 8/17

isso funciona, porque set -xmostra a cada linha antes de ser executado
rubo77


1

Se você precisar em uma variável a validade de todos os arquivos em um diretório (gancho de pré-confirmação do git, script build lint), poderá capturar a saída stderr dos comandos "sh -n" ou "bash -n" (consulte outros respostas) em uma variável e tenha um "if / else" com base nesse

bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \;  2>&1 > /dev/null)
  if [ "$bashErrLines" != "" ]; then 
   # at least one sh file in the bin dir has a syntax error
   echo $bashErrLines; 
   exit; 
  fi

Mude "sh" com "bash" dependendo das suas necessidades

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.