Como depurar um script bash?

113

Estou tendo alguns problemas com alguns scripts no bash, sobre erros e comportamentos inesperados. Eu gostaria de investigar as causas dos problemas para poder aplicar correções. Existe uma maneira que eu possa transformar algum tipo de "modo de depuração" para bash, para obter mais informações?

    
por Braiam 14.09.2014 / 16:41

8 respostas

103

Inicie seu script bash com bash -x ./script.sh ou adicione seu script set -x para ver a saída de depuração.

Adicional com bash 4.1 ou posterior:

Se você quiser gravar a saída de depuração em um arquivo separado, adicione isso ao seu script:

exec 5> debug_output.txt
BASH_XTRACEFD="5"

Veja: link

Se você quiser ver números de linha, adicione isto:

PS4='$LINENO: '

Se você tiver acesso ao comando logger , poderá usá-lo para gravar a saída de depuração por meio do seu syslog com registro de data e hora, nome do script e número da linha:
#!/bin/bash

exec 5> >(logger -t $0)
BASH_XTRACEFD="5"
PS4='$LINENO: '
set -x

# Place your code here

Você pode usar o comando option -p of logger para definir um recurso e nível individuais para gravar a saída via syslog local em seu próprio arquivo de log.

    
por 14.09.2014 / 16:55
43

Usando set -x

Eu sempre uso set -x e set +x . Você pode envolver as áreas em que deseja ver o que está acontecendo com elas para aumentar ou diminuir a verbosidade.

#!/bin/bash

set -x
..code to debug...
set +x

log4bash

Além disso, se você fez um trabalho de desenvolvimento e está familiarizado com o estilo dos registradores que usam os nomes log4j, log4perl, etc., talvez você queira usar log4bash .

trecho

Let's face it - plain old echo just doesn't cut it. log4bash is an attempt to have better logging for Bash scripts (i.e. make logging in Bash suck less).

De lá, você pode fazer coisas assim em seus scripts Bash:

#!/usr/bin/env bash
source log4bash.sh

log "This is regular log message... log and log_info do the same thing";

log_warning "Luke ... you turned off your targeting computer";
log_info "I have you now!";
log_success "You're all clear kid, now let's blow this thing and go home.";
log_error "One thing's for sure, we're all gonna be a lot thinner.";

# If you have figlet installed -- you'll see some big letters on the screen!
log_captains "What was in the captain's toilet?";

# If you have the "say" command (e.g. on a Mac)
log_speak "Resistance is futile";

Resultando neste tipo de resultado:

log4sh

Sevocêprecisardealgomaisportátil,hátambémoantigolog4sh.Funcionadeformasemelhantealog4bash,disponívelaqui:

  • link
por 14.09.2014 / 19:52
31

Existe um depurador básico, o bashdb , que é um pacote instalável em muitas distros. Ele usa o modo de depuração estendido interno do bash ( shopt -s extdebug ). Parece muito com o gdb; aqui está uma sessão de amostra para dar um sabor:

$ ls
1st.JPG  2ndJPG.JPG
$ cat ../foo.sh
for f in *.JPG
do
  newf=${f/JPG/jpg}
  mv $f $newf
done
$ bashdb ../foo.sh
(foo.sh:1):
1:      for f in *.JPG
bashdb<0> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<1> next
(foo.sh:4):
4:        mv $f $newf

Como no gdb, a instrução é mostrada apenas antes de estar prestes a ser executada. Assim, podemos examinar variáveis para ver o que a declaração fará antes de fazê-lo.

bashdb<2> print $f $newf
1st.JPG 1st.jpg
bashdb<3> next
(foo.sh:1):
1:      for f in *.JPG
bashdb<4> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<5> next
(foo.sh:4):
4:        mv $f $newf
bashdb<6> print $f $newf
2ndJPG.JPG 2ndjpg.JPG

Não é isso que queremos! Vamos ver a expansão do parâmetro novamente.

bashdb<7> print $f ${f/JPG/jpg}
2ndJPG.JPG 2ndjpg.JPG
bashdb<8> print $f ${f/JPG$/jpg}
2ndJPG.JPG 2ndJPG.JPG
bashdb<9> print $f ${f/%JPG/jpg}
2ndJPG.JPG 2ndJPG.jpg

OK, isso funciona. Vamos definir newf para o valor correto.

bashdb<10> eval newf=${f/%JPG/jpg}
$? is 0
bashdb<11> print $f $newf
2ndJPG.JPG 2ndJPG.jpg

Parece bom. Continue o script.

bashdb<12> next
Debugged program terminated normally. Use q to quit or R to restart.
$ ls
1st.jpg  2ndJPG.jpg
    
por 15.09.2014 / 23:12
19

O método padrão para depurar scripts na maioria dos shells baseados em Bourne, como o bash, é escrever set -x no topo do seu script. Isso fará o bash mais detalhado sobre o que está sendo feito / executado e como os argumentos são avaliados.

-x  Print commands and their arguments as they are executed.

isto é útil para o intérprete ou para os scripts internos. Por exemplo:

$ find "$fileloc" -type f -prune "$filename" -print
+ find /var/adm/logs/morelogs -type f -prune '-name *.user' -print
find: unknown predicate '-name *.user'
$ find "$fileloc" -type f -prune $filename -print
+ find /var/adm/logs/morelogs -type f -prune -name '*.user' -print
find: '/var/adm/logs/morelogs': No such file or directory

Acima, podemos ver por que o achado está falhando devido a algumas aspas simples.

Para desativar o recurso, basta digitar set +x .

    
por 14.09.2014 / 16:41
11

Usando o Eclipse

Você pode usar o ambiente combinado do Eclipse e Shelled com o script "_DEBUG.sh" vinculado abaixo.

  • Eclipse Shelled Plug-in:
    link
  • debugger bash - só funciona com o shelled: link

Alternando shells

Por padrão, a ferramenta de desenvolvimento Shelled usa /bin/dash como o interpretador. Eu mudei isso para /bin/bash para ter melhor compatibilidade com a maioria dos exemplos de shell na web e meu ambiente.

OBSERVAÇÃO: Você pode alterar isso indo para: Window - > Preferência - > Script da Shell - > Intérpretes

Instruções de configuração

O pacote Debugger tem as etapas para usar o script _DEBUG.sh para sua depuração de script, que é basicamente (o readme.txt):

  1. Create Shell Script Project: File -> New -> Other -> Shell Script -> Shell Script Project Wizard.
  2. Create a Bash script file: File -> New -> File. For this example, it will be script.sh. Extension should be ".sh" and is a must.
  3. Copy the file _DEBUG.sh to project folder.
  4. Insert the following text to the top of the file script.sh:

    . _DEBUG.sh
    
  5. If the file is created in Microsoft Windows then be sure to execute the File -> Convert Line Delimiters To -> Unix.

  6. Set up a debug launch configuration: Run -> Debug Configurations -> Bash script... There are 2 fields to set here:

    a) "Bash script:" - Path in workspace of Eclipse to the Bash script to debug.
    e) "Debugger port:" 33333

  7. Switch to The Debug perspective. Start the debugging session. Launch script.sh from bash shell.

A interface de depuração do bash

Esse depurador bash possui os recursos completos dos depuradores de programação padrão, como:

  • Alternar ponto de quebra
  • Operação passo-a-passo única
  • Step-in, Step-out, funções de sobreposição e sub-rotinas
  • Examinando código ou variáveis a qualquer momento enquanto o script está sendo executado

O IDE (Ambiente de Desenvolvimento Integrado) do Shelled (Shell Script Editor) tem um bônus adicional de realizar a verificação de contexto, realce e recuo ao escrever seu script. Se não recuar corretamente, você poderá imediatamente sinalizar muitos erros locais.

Depois, há outros benefícios do IDE , como:

  • lista de tarefas TODO
  • Tarefa Mylyn
  • lista de marcadores
  • Edição de várias janelas
  • Compartilhamento remoto do ambiente
por 14.09.2014 / 18:36
6

Um recurso maravilhoso apareceu nos últimos anos: link

mostra-lhe mais do que o normal, permitindo encontrar facilmente aquelas citações não fechadas ou chaves, etc.

Apenas certifique-se de não colar informações importantes (ips, senhas, etc) pela rede ... (especialmente porque é http, não criptografado) (acredito que o shellcheck também está disponível para download, mas não tenho certeza )

    
por 30.05.2015 / 09:53
3

simplesmente use:

#!/bin/bash -x

o mesmo para o shell:

#!/bin/sh -x
    
por 14.09.2014 / 19:55
2

Hoje em dia, existe a Depuração de Bash do Código VS.

link

Tem "Step in / out / over" e também mostra o valor de cada variável.

    
por 22.02.2017 / 20:27