Existe alguma maneira de depurar um script bash? Por exemplo, algo que imprime um tipo de log de execução como "linha de chamada 1", "linha de chamada 2" etc.
Eles fornecem um rastro do que está sendo executado. (Veja também 'Esclarecimento' na parte inferior da resposta.)
Às vezes, você precisa controlar a depuração no script. Nesse caso, como Cheeto me lembrou , você pode usar:
set-x
Isso ativa a depuração. Você pode desativá-lo novamente com:
set+x
(Você pode descobrir o estado de rastreamento atual analisando $-os sinalizadores atuais para x.)
Além disso, os shells geralmente fornecem opções ' -n' para 'sem execução' e ' -v' para o modo 'detalhado'; você pode usá-los em conjunto para verificar se o shell pensa que poderia executar seu script - ocasionalmente útil se você tiver uma cotação desequilibrada em algum lugar.
Há alegações de que a -xopção ' ' no Bash é diferente de outros shells (veja os comentários). O Manual do Bash diz:
-x
Imprima um rastro de comandos simples, forcomandos, casecomandos, selectcomandos e forcomandos aritméticos e seus argumentos ou listas de palavras associadas depois de expandidos e antes de serem executados. O valor da PS4variável é expandido e o valor resultante é impresso antes do comando e de seus argumentos expandidos.
Isso parece não indicar um comportamento diferente. Não vejo outras referências relevantes para ' -x' no manual. Não descreve diferenças na sequência de inicialização.
Esclarecimento : Em sistemas como uma caixa típica do Linux, onde ' /bin/sh' é um link simbólico para ' /bin/bash' (ou onde quer que o executável Bash seja encontrado), as duas linhas de comando atingem o efeito equivalente de executar o script com o rastreamento de execução ativado. Em outros sistemas (por exemplo, Solaris, e algumas variantes mais modernas do Linux), /bin/shnão é o Bash, e as duas linhas de comando dariam resultados (ligeiramente) diferentes. Mais notavelmente ' /bin/sh', seria confundido por construções no Bash que ele não reconhece. (No Solaris, /bin/shé um shell Bourne; no Linux moderno, às vezes é Dash - um shell menor, mais estritamente apenas para POSIX.) Quando invocado por nome como esse, a linha 'shebang' ( #!/bin/bash'vs '#!/bin/sh'
O manual do Bash possui uma seção no modo Bash POSIX que, ao contrário de uma versão antiga e errônea desta resposta (veja também os comentários abaixo), descreve detalhadamente a diferença entre 'Bash chamado como sh' e 'Bash chamado como bash'
Ao depurar um script de shell (Bash), será sensato e sensato - até necessário - usar o shell nomeado na linha shebang com a -xopção Caso contrário, você poderá (obterá) comportamento diferente ao depurar e ao executar o script.
Ele especificou um bashscript. A execução de um script bash sh -xfará com que ele se comporte completamente diferente! Atualize sua resposta.
Lhunath
1
@lhunath: De que maneira 'sh -x' (ou 'bash -x') faz um script se comportar de maneira completamente diferente? Obviamente, ele gera informações de rastreamento para o stderr; isso é um dado (embora não mencionado na minha resposta). Mas o que mais? Uso 'bash' como 'sh' no Linux e MacOS X e não percebi um problema sério.
31416 Jonathan Leffler
6
Existem diferenças, na inicialização e no tempo de execução. Eles estão totalmente documentados na distribuição do Bash.
TheBonsai
4
Aqui está um link para o documento do bash: gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files 'Se o Bash for chamado com o nome sh, ele tentará imitar o comportamento de inicialização de versões históricas do sh como tanto quanto possível, enquanto em conformidade com o padrão POSIX bem'
thethinman
6
E use o prompt do PS4 para fornecer informações mais úteis, como:export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
estani
28
Eu usei os seguintes métodos para depurar meu script.
set -efaz o script parar imediatamente se algum programa externo retornar um status de saída diferente de zero. Isso é útil se o seu script tentar lidar com todos os casos de erro e onde uma falha nesse procedimento deve ser interceptada.
set -x foi mencionado acima e é certamente o mais útil de todos os métodos de depuração.
set -n também pode ser útil se você deseja verificar se há erros de sintaxe no seu script.
stracetambém é útil para ver o que está acontecendo. Especialmente útil se você não tiver escrito o script.
Rastrear um script (ou seja, rastrear um shell executando o script) é um método estranho de depuração de shell (mas pode funcionar para um conjunto limitado de problemas).
TheBonsai
1
Admito que é estranho e também muito detalhado, mas se você limitar a saída do strace a alguns syscalls, isso se tornará útil.
1
Observe que isso strace -fé necessário se você também deseja encontrar erros nos processos iniciados pelo script. (o que o torna muitas vezes mais detalhado, mas ainda útil se você o limitar aos syscalls nos quais está interessado).
Mas acho que os métodos de depuração de script "padrão" são ineficientes, não intuitivos e difíceis de usar. Para aqueles acostumados a depuradores sofisticados de GUI que colocam tudo ao seu alcance e facilitam o trabalho para problemas fáceis (e possíveis para problemas difíceis), essas soluções não são muito satisfatórias.
O que faço é usar uma combinação de DDD e bashdb. O primeiro executa o último e o último executa seu script. Isso fornece uma interface do usuário com várias janelas com a capacidade de percorrer o código no contexto e exibir variáveis, pilha, etc., sem o esforço mental constante para manter o contexto em sua cabeça ou continuar listando novamente a fonte.
Acabei de descobrir ddd graças à sua resposta. No Ubuntu 12.04.3 (64bit), a versão apt-sources não funciona. Eu tive que compilar e instalar a partir da fonte para começar a depurar meu script bash. As instruções aqui - askubuntu.com/questions/156906/… ajudaram.
chronodekar
Sim, isso é um problema. Eu resolvi lhe algum tempo de volta com algum scripting - instalações 'dddbash' / constrói DDD, remove a versão antiga, se é errado, instala bashdb, etc. (Resposta foi editado com esta informação agora)
Stabledog
10
Você também pode escrever "set -x" dentro do script.
$ cat test.sh
ARRAY=("hello there" world)for x in $ARRAY;do
echo $xdone
$ shellcheck test.sh In test.sh line 3:for x in $ARRAY;do^-- SC2128:Expanding an array without an index only gives the first element.
corrigir o erro, primeira tentativa ...
$ cat test.sh
ARRAY=("hello there" world)for x in ${ARRAY[@]};do
echo $xdone
$ shellcheck test.shIn test.sh line 3:for x in ${ARRAY[@]};do^-- SC2068:Double quote array expansions, otherwise they're like $* and break on spaces.
Para shell: Faça o download do zip e importe-o para o eclipse via ajuda -> instalar novo software: arquivo local Para o basheclipse: Copie os frascos no diretório dropins do eclipse
Esta é uma resposta apenas para o limite do link (veja também aqui ). Você deve expandir sua resposta para incluir o máximo de informações possível aqui, pelo menos o mínimo necessário para realmente realizar o que está sugerindo e usar os links apenas para referência. Basicamente, as postagens no Stack Overflow (e todo o Stack Exchange) devem ser independentes. Isso significa que informações suficientes precisam estar em sua resposta, de modo que o leitor não precise sair do local para obter instruções. No momento, esse não é o caso desta resposta.
Makyen 8/08/19
esta é a primeira resposta que encontrei depois de analisar muitas que realmente mostram que a depuração verdadeira é possível. As respostas padrão "set + x" correspondem perfeitamente a uma resposta independente, mas quase intencionalmente ignoram as verdadeiras perguntas sobre a depuração verdadeira. Aplaudo esta resposta 👏
Atualmente, o BDB é suportado nos idiomas inglês e espanhol. Para alterar o idioma, editar o arquivo / etc / default / bdb
abadjm
a captura de tela parece interessante, mas não consegui executá-la "bdb.sh: linha 32: bdbSTR [1]: variável não acoplada"; btw mostrará os valores atuais de todas as variáveis definidas a cada passo que fazemos no código?
Potência de Aquário
2
ajuste + x = @ECHO OFF, ajuste -x = @ECHO ON.
Você pode adicionar uma -xvopção ao Shebang padrão da seguinte maneira:
#!/bin/bash -xv
-x: Exibe comandos e seus argumentos à medida que são executados. -v: Exibe as linhas de entrada do shell conforme são lidas.
ltraceé outro utilitário Linux semelhante ao strace. No entanto, ltracelista todas as chamadas de biblioteca que estão sendo chamadas em um processo executável ou em execução. Seu próprio nome vem do rastreamento de chamadas de biblioteca. Por exemplo:
A postagem tem detalhes sobre a introdução de níveis de log como INFO, DEBUG, ERROR. Detalhes de rastreamento, como entrada de script, saída de script, entrada de função, saída de função.
Respostas:
Eles fornecem um rastro do que está sendo executado. (Veja também 'Esclarecimento' na parte inferior da resposta.)
Às vezes, você precisa controlar a depuração no script. Nesse caso, como Cheeto me lembrou , você pode usar:
Isso ativa a depuração. Você pode desativá-lo novamente com:
(Você pode descobrir o estado de rastreamento atual analisando
$-
os sinalizadores atuais parax
.)Além disso, os shells geralmente fornecem opções '
-n
' para 'sem execução' e '-v
' para o modo 'detalhado'; você pode usá-los em conjunto para verificar se o shell pensa que poderia executar seu script - ocasionalmente útil se você tiver uma cotação desequilibrada em algum lugar.Há alegações de que a
-x
opção ' ' no Bash é diferente de outros shells (veja os comentários). O Manual do Bash diz:-x
Imprima um rastro de comandos simples,
for
comandos,case
comandos,select
comandos efor
comandos aritméticos e seus argumentos ou listas de palavras associadas depois de expandidos e antes de serem executados. O valor daPS4
variável é expandido e o valor resultante é impresso antes do comando e de seus argumentos expandidos.Isso parece não indicar um comportamento diferente. Não vejo outras referências relevantes para '
-x
' no manual. Não descreve diferenças na sequência de inicialização.Esclarecimento : Em sistemas como uma caixa típica do Linux, onde '
/bin/sh
' é um link simbólico para '/bin/bash
' (ou onde quer que o executável Bash seja encontrado), as duas linhas de comando atingem o efeito equivalente de executar o script com o rastreamento de execução ativado. Em outros sistemas (por exemplo, Solaris, e algumas variantes mais modernas do Linux),/bin/sh
não é o Bash, e as duas linhas de comando dariam resultados (ligeiramente) diferentes. Mais notavelmente '/bin/sh
', seria confundido por construções no Bash que ele não reconhece. (No Solaris,/bin/sh
é um shell Bourne; no Linux moderno, às vezes é Dash - um shell menor, mais estritamente apenas para POSIX.) Quando invocado por nome como esse, a linha 'shebang' (#!/bin/bash
'vs'#!/bin/sh
'O manual do Bash possui uma seção no modo Bash POSIX que, ao contrário de uma versão antiga e errônea desta resposta (veja também os comentários abaixo), descreve detalhadamente a diferença entre 'Bash chamado como
sh
' e 'Bash chamado comobash
'Ao depurar um script de shell (Bash), será sensato e sensato - até necessário - usar o shell nomeado na linha shebang com a
-x
opção Caso contrário, você poderá (obterá) comportamento diferente ao depurar e ao executar o script.fonte
bash
script. A execução de um script bashsh -x
fará com que ele se comporte completamente diferente! Atualize sua resposta.export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
Eu usei os seguintes métodos para depurar meu script.
set -e
faz o script parar imediatamente se algum programa externo retornar um status de saída diferente de zero. Isso é útil se o seu script tentar lidar com todos os casos de erro e onde uma falha nesse procedimento deve ser interceptada.set -x
foi mencionado acima e é certamente o mais útil de todos os métodos de depuração.set -n
também pode ser útil se você deseja verificar se há erros de sintaxe no seu script.strace
também é útil para ver o que está acontecendo. Especialmente útil se você não tiver escrito o script.fonte
strace -f
é necessário se você também deseja encontrar erros nos processos iniciados pelo script. (o que o torna muitas vezes mais detalhado, mas ainda útil se você o limitar aos syscalls nos quais está interessado).set -e
é ... controverso .Esta resposta é válida e útil: https://stackoverflow.com/a/951352
Mas acho que os métodos de depuração de script "padrão" são ineficientes, não intuitivos e difíceis de usar. Para aqueles acostumados a depuradores sofisticados de GUI que colocam tudo ao seu alcance e facilitam o trabalho para problemas fáceis (e possíveis para problemas difíceis), essas soluções não são muito satisfatórias.
O que faço é usar uma combinação de DDD e bashdb. O primeiro executa o último e o último executa seu script. Isso fornece uma interface do usuário com várias janelas com a capacidade de percorrer o código no contexto e exibir variáveis, pilha, etc., sem o esforço mental constante para manter o contexto em sua cabeça ou continuar listando novamente a fonte.
Há orientações sobre como configurar isso aqui: http://ubuntuforums.org/showthread.php?t=660223
fonte
Você também pode escrever "set -x" dentro do script.
fonte
Encontrei o utilitário shellcheck e algumas pessoas acham interessante https://github.com/koalaman/shellcheck
Um pequeno exemplo:
corrigir o erro, primeira tentativa ...
Vamos tentar de novo...
encontre agora!
É apenas um pequeno exemplo.
fonte
Instale o VSCode , adicione a extensão de depuração do bash e você estará pronto para depurar no modo visual. veja Aqui em ação.
fonte
Use eclipse com os plugins com shell e basheclipse.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Para shell: Faça o download do zip e importe-o para o eclipse via ajuda -> instalar novo software: arquivo local Para o basheclipse: Copie os frascos no diretório dropins do eclipse
Siga as etapas fornecidas https://sourceforge.net/projects/basheclipse/files/?source=navbar
Eu escrevi um tutorial com muitas capturas de tela em http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html
fonte
Eu construí um depurador Bash. Apenas tente. Espero que ajude https://sourceforge.net/projects/bashdebugingbash
fonte
Você pode adicionar uma
-xv
opção ao Shebang padrão da seguinte maneira:-x
: Exibe comandos e seus argumentos à medida que são executados.-v
: Exibe as linhas de entrada do shell conforme são lidas.ltrace
é outro utilitário Linux semelhante aostrace
. No entanto,ltrace
lista todas as chamadas de biblioteca que estão sendo chamadas em um processo executável ou em execução. Seu próprio nome vem do rastreamento de chamadas de biblioteca. Por exemplo:Fonte
fonte
Eu acho que você pode tentar este depurador Bash: http://bashdb.sourceforge.net/ .
fonte
Algum truque para depurar festança scripts:
Usando
set -[nvx]
Além de
e
para parar o despejo.
Eu gostaria de falar sobre
set -v
qual despejo é menor e menos desenvolvido.Despejar variáveis ou rastreamento em tempo real
Para testar algumas variáveis, eu uso em algum momento isso:
para adicionar:
na linha 18 e executando o script resultante (com args ), sem precisar editá-los.
claro, isso poderia ser usado para adicionar
set [+-][nvx]
:adicionará
declare -p v1 v2 >&2
após a linha 18,set -x
antes da linha 22 eset +x
antes da linha 26.pequena amostra:
Nota: Os cuidados
$LINENO
serão afetados por modificações on-the-fly !(Para ver o script resultante sem execução, basta soltar
bash <(
e) arg1 arg2
)Passo a passo, tempo de execução
Dê uma olhada na minha resposta sobre como criar perfis de bash scripts
fonte
Há uma boa quantidade de detalhes no registro de scripts de shell por meio de variáveis globais do shell. Podemos emular o tipo semelhante de log no shell script: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
A postagem tem detalhes sobre a introdução de níveis de log como INFO, DEBUG, ERROR. Detalhes de rastreamento, como entrada de script, saída de script, entrada de função, saída de função.
Exemplo de log:
fonte