Shell Script Debugging: A arte de encontrar erros


- Mensagens mais comuns

1. syntax error: unexpected end of file
Quando criamos um laço ou condiçao, e não o 'fechamos', ou seja, nao colocamos o 'done' ou 'fi' ao final.

Ou seja, não estava esperando o final do arquivo. Interprete como 'era pra ser outra coisa., não esqueceu nada no caminho?'

2. unexpected EOF while looking for matching `”’
Quantos esquecemos de completar as aspas ", ` ou ', aparece algo parecido.

Nesse caso, ele não informa a linha. Então, se o código for muito grande fica bem difícil de achar o erro.
Um editor de texto com a opçao 'highlighting' ajuda bastante. Indico o vi/vim.

3. command not found

Se viu isso, muito provavelmente digitou algo errado. As vezes é simplesmente um espaço que falta dentro de um 'if', por exemplo.
if[errado ]
if[ certo ]

Isso porque o '[' é um comando, é uma maneira mais simples do comando 'test' e ']' é um argumento pro comando '['.


Lembrando que, caso usemos uma variável, por exemplo: if[$a...]
O shell apontará o erro, mas não como: [$a
E sim usando o valor da variável. Por exemplo, se a=1, o erro será: [1
O que pode vir a confundir um pouco.


Então, o [errado = testerrado , ou seja, voce realmente digitou o comando de forma errada.
Interessante, não?


- Alguns cuidados

Caso vá fazer script importantes, que não serão usados somente por você, tome algumas precauções:

1. Nem todos os sistemas vem com um compilador de C. Se vier, pode ser diferente, pode ser o gcc, cc ou lpicc.

2. Há comandos que não são iguais em sistemas diferents, como o 'ps', pra listar os processos, que usamos as opçoes 'aux' ou 'ef' dependendo do SO.

3. Cuidado com os dispositivos. Pode se deparar com /mnt/cdrom ou /media/cdrom .

4. Quando o shell encontra o erro, ele morre, e o que vem em seguida não é rodado.
Isso é um risco, pois o que viria a seguir seriam ações que complementariam, remendariam ou concluiriam os comandos anteriores, podendo deixar seu sistema instável ou inseguro.

- 'exit' ou 'read' e descubra

Em um script muito longo, é uma boa técnica inserir uns 'exit' no código. Caso o script rode bem, o erro estará depois do exit.
Se acontecer um bug, você sabe que até o 'exit' tem pelo menos um erro.
Coloque sempre no meio do script. Depois no meio da metade que o erro está localizado...é o algoritmo de busca binary search.

Podemos parar o script de uma forma menos agressiva. Em vez de saírmos, vamos dar uma pausa nele para simplesmente para fazer com que ele peça e leia uma variável do usuário. Se até então não tiver ocorrido erros, está ok nessa parte do script. Use 'echo's pra se situar.

- 'function'

Se a dificuldade persistir, divida os blocos do script em funções e execute todas na ordem, como se o script estivesse rodando normalmente. O Shell deve acusar a função com erro.

- 'echo'

Entupa o script de 'echos' do tipo "o comando tal passou", "o looping já era", "a condição nao bugou", etc.

- O mas próximo que podemos chegar de um debugging

Em shell, não existe um debugger propriamente dito, como os de outras linguagens, a quais estamos acostumados.
Mas do artigo de Pipelines, vimos que cada comando tem sua saída de erros (stderr). Ao invés de debuggar, podemos pedir pro shell exibir mais informações a medida que ele analisa o script, através das opções '-n', '-v' e '-x'.


  • -n

checa a sintaxe, sem executar os comandos do script
sh -n nao_rode

Use sempre que necessitar de segurança.


  • -v

O 'v' é de verbose, é a mesma técnica de entupir o script com 'echo's.
Aqui, o shell informa que comando vai rodar. Um por um.
sh -v fale_shell

Se você for rodar scripts de fontes duvidosas, uma boa prática é combinar esses dois comandos:
sh -nv sou_cauteloso


  • -t

Se estiver com problemas de valores de variáveis e quiser checar se elas estão se comportando (mudando) de maneira correta, use o 'execution trace', e vejo o traço de mudanças:
sh -t mude_e_mostre


- Boas práticas


  • Seja como o Unix.
  • Pense como o Unix.
  • Imite o Unix.
  • Nomeie variáveis de modo a fazer sentido.
  • Armazene endereços, de arquivous e diretórios, em variáveis. Assim evita a escrita repetida do endereço pelo script.
  • Use parágrafos para separar trechos [ENTER].
  • Idente loops e condições.
  • Comente seus scripts, nem que seja só a primeira linha, dizendo pra que serve o script. Daqui há alguns meses você vai entender porquê isso é importante.
  • Erros são tão comuns e 'importantes', que o Unix tem mensagem de erro até pra quando as coisas dão certo (?). Faça o mesmo. Forneça erros bem escritos, explicativos e de maneira mais direta possível em seus scripts.
  • A época das cavernas acabou. Não escreva seu código em forma de códigos (sacou?) incompreensíveis. Seja claro e simples, não use hieróglifos. Se for compartilhar, vale muito mais um código fácil de ler do quê um minimalista.
  • Projetos grandes e complexos são feitos partes pequenas e simples. A cada etapa de seu código, teste-o. Só vá para o próximo depois de testar completamente o trecho atual. Não deixe nada passar, ou vai virar uma bola de neve invisível.
  • Escute Rush.



- Uma segunda opinião

Todos já passamos pela situação de ficar minutos, horas ou dias procurando o erro e tentamos suicídio quando descobrimos o quão bobo ele era.
É difícil achar erros em nossos códigos, pra gente, sempre faz sentido.
Simplesmente peça pra outra pessoa dar uma olhada.

Nenhum comentário: