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.