Acesso direto ao conteúdo
Logotipo Dicas-L, por Ricardo Burile
Visite também: Ipok ·  Segurança Linux ·  UnderLinux ·  VivaOLinux ·  LinuxSecurity ·  NoticiasLinux ·  BR-Linux ·  SoftwareLivre.org ·  [mais]   
 

Você está aqui: Home  → Arquivo Dicas-L

 

Lan University - Certificações e Qualificações em TI

Assine a Lista Dicas-L

Receba diariamente por email as dicas
de informática publicadas neste site
Para se descadastrar, clique aqui.

Problemas IDIOTAMENTE comuns quando se cria um script em Shell

Colaboração: Rafael Henrique da Silva Correia

Data de Publicação: 18 de junho de 2012

Olhando o script abaixo (sem escrevê-lo no Shell :P) o que você diria que ele escreve na tela?? Lembrando que a variável $? informa o retorno do status do último comando se o comando executou com sucesso ele será 0, se o comando deu algum erro ele será diferente de 0. Olhe:

  #!/bin/bash
  echo "TESTANDO 123..."
  if [ "$?" -ne 0 ]; then
    echo "não igual a 0"
  elif [ "$?" -eq 0 ]; then
    echo "igual a 0"
  else
    echo "Nem um nem outro"
  fi

Se você achou (assim como eu achei) que ele escreveria na tela "não igual a 0" você está redondamente enganado! Descobri que cometi um erro deste tipo em um script que eu estava fazendo (com certeza muuuuito maior do que este).

Por que o script tem este comportamento?

A variável $? como citado acima informa o retorno do status do último comando se o comando executou com sucesso ele será 0, se o comando deu algum erro ele será diferente de 0 .... porém o if faz uso do comando test (representado por []), então o primeiro if retornará um status e esse novo status será armazenado dentro de $?, desta forma DESGRAÇANDO todo o script.

E para corrigir?

Para corrigir basta criar uma variável auxiliar desta forma:

  #!/bin/bash
  
  echo "TESTANDO 123..."
  VARAUX="$?"
  
  if [ "$VARAUX" -ne 0 ]; then
    echo "não igual a 0"
  elif [ "$VARAUX" -eq 0 ]; then
    echo "igual a 0"
  else
    echo "Nem um nem outro"
  fi

Eis que agora a saída do script será:

  rafael@zion:~$ ./teste1.sh
  TESTANDO 123...
  igual a 0

Como depurar programas em shell?

Geralmente no caso deste problema eu faria o seguinte, escreveria echos para ver o conteúdo da variável $? durante a execução do script da seguinte maneira:

  #!/bin/bash
  echo "TESTANDO 123..."
  echo "$?"
  if [ "$VARAUX" -ne 0 ]; then
    echo "$?"
    echo "não igual a 0"
  elif [ "$VARAUX" -eq 0 ]; then
    echo "$?"
    echo "igual a 0"
  else
    echo "$?"
    echo "Nem um nem outro"
  fi

E para finalizar existe um parâmetro muito bom do bash próprio para fins de depuração:

  rafael@zion:~$ bash -x teste1.sh
  + echo 'TESTANDO 123...'
  TESTANDO 123...
  + echo 0
  0
  + '[' '' -ne 0 ']'
  teste1.sh: line 6: [: : esperado expressão de número inteiro
  + '[' '' -eq 0 ']'
  teste1.sh: line 11: [: : esperado expressão de número inteiro
  + echo 2
  2
  + echo 'Nem um nem outro'
  Nem um nem outro

Desta forma você conseguirá ver que rumo seu script está tomando!

Esta dica não é nada complexa, porém agradeço se alguém postar outras formas de depuração de scripts em shell, eu somente iniciei o assunto e aqui no Dicas-l já li muitos comentários legais e construtivos a respeito das dicas que eu já postei!

Conhecimento traz conhecimento! Vamos colaborar!

Até+

 

 

Veja a relação completa dos artigos de Rafael Henrique da Silva Correia

Formato PDF
Newsfeed RSS
Formato para impressão
PDF RSS Imprimir

Referências Adicionais

Referências adicionais sobre os assuntos abordados neste site podem ser encontradas em nossa Bibliografia.

Avalie esta dica

  • Currently 2.95/5
  • 1
  • 2
  • 3
  • 4
  • 5

Avaliação: 3.0 /5 (546 votos)

Opinião dos Leitores

Rafael Henrique da Silva Correia
28 Jun 2012, 08:44
Obrigado a todos pelos comentários!
Rafael Henrique da Silva Correia
28 Jun 2012, 08:43
Sérgio Luiz Araújo Silva ... isso funciona

comando desejado && echo "ok" || echo "deu pau no comando"

Porém se eu tenho que testar 3 ou 4 comandos usando and e or isso fica muito complicado. Quando eu jogo o valor do status em uma variável consigo usar os ifs da forma que eu desejar.

Até+
Rafael Henrique da Silva Correia
28 Jun 2012, 08:40
Fernando Roxo muito boa dica! Usarei o -xv com certeza!
Rafael Henrique da Silva Correia
28 Jun 2012, 08:39
Simmm pessoal o else está lá desnecessariamente... porém isso é um script altamente didático e não tem função útil.
Rafael Henrique da Silva Correia
28 Jun 2012, 08:38
Zé, o título tem que parecer engraçado ao meu ver... se o título não chama atenção eu geralmente nem abro a dica para ler.
Rafael Henrique da Silva Correia
28 Jun 2012, 08:37
Caro Alysson Bruno o script final é este:

#!/bin/bash

echo "TESTANDO 123..."
VARAUX="$?"

if [ "$VARAUX" -ne 0 ]; then
echo "não igual a 0"
elif [ "$VARAUX" -eq 0 ]; then
echo "igual a 0"
else
echo "Nem um nem outro"
fi

Portanto O VARAUX vai pegar o status do comando echo, pois este é o objetivo do script.

27 Jun 2012, 07:35
Caro Rafael Henrique da Silva Correia,

Seu titulo não ficou bom.

Bruno Jesus
18 Jun 2012, 18:40
Se o valor não é zero ele vai mostrar o primeiro texto, se não ele tem que ser zero. Não precisa da segunda comparação. Atualmente o else lá é desnecessário, certo?
Fernando Roxo
18 Jun 2012, 16:21
Quanto ao "debug", todos os meus scripts têm no início um texto do tipo :

# Debug
# set -xv

Sim, o comando "set" acima está comentado. Para ativá-lo basta descomentar a linha. Mas porque "-xv" e não "-x" ? Porque o "-v" vai listar a linha de comando *antes* da expansão/substituição, mostrando a linha antes e depois podemos verificar se a substituição foi a que se queria.

No caso específico deste tipo de código me parece só haver 2 possibilidades para a comparação, ou é igual a zero ou diferente. A opção "nenhum dos dois" não parece ter muita utilidade. Portanto bastaria haver as cláusulas "if" e "else", o que torna necessária a variável VARAUX.

Atenção, eu não estou dizendo que a variável não tem utilidade ! Em várias situações existe mesmo a necessidade. Por razões históricas, do tempo que trilobita era tira-gosto, eu uso RC (return code, coisa de mainframe, imagine só. :)). No caso de querer tratar vários valores eu uso algo como :

<comando>
RC=$?

case "$RC" in
0) echo "Tudo bem..."
;;

[1-5]) echo "Erro entre 1 e 5"
;;

127) echo "Arquivo não encontrado"
;;

*) echo "Erro $RC desconhecido, abortando."
exit $RC
;;
esac

Provavelmente a interface WEB vai destruir a estruturação do texto, mas acho que vai dar para entender. :)

Felipe Santos - Rasputin
18 Jun 2012, 15:21
Uma outra dica pra depurar scripts em sheel é utilizar o comando set -x no inicio do comando. assim ele irá printar todos os passos executaos pelo script
Raul Libório
18 Jun 2012, 12:23
Concordo e faço como o Sérgio.
Por exemplo, em scripts que necessitem criar um diretório, faço da seguinte maneira:

[ -d /path/do/diretorio ] || mkdir /path/do/diretorio

Aqui ele verificará se o diretório existe. Caso não, ele o criará.
Alysson Bruno
18 Jun 2012, 07:25
echo também é um comando do Shell Script, então seu script está errado, você deve colocar o VARAUX antes do echo também.
Sérgio Luiz Araújo Silva
18 Jun 2012, 06:54
Não sou assim tão bom em shell mas acho que há outro caminho

comando desejado && echo "ok" || echo "deu pau no comando"

caso o comando dê certo o shell mostra ok, caso contrário
ele vai para o "ou" mostrando a mensagem de erro
*Nome:
Email:
Me notifique sobre novos comentários nessa página
Oculte meu email
*Texto:
 
  Para publicar seu comentário, digite o código contido na imagem acima
 


Powered by Scriptsmill Comments Script


 

Read in English - Uma Maneira Divertida de Aprender Inglês