Estou tentando criar alguns relatórios de erros usando um trap para chamar uma função em todos os erros:
Trap "_func" ERR
É possível obter de que linha o sinal ERR foi enviado? O shell é uma festança.
Se fizer isso, posso ler e relatar qual comando foi usado e registrar / executar algumas ações.
Ou talvez eu esteja indo para tudo errado?
Eu testei com o seguinte:
#!/bin/bash
trap "ECHO $LINENO" ERR
echo hello | grep "asdf"
E $LINENO
está retornando 2. Não está funcionando.
bash
shell-script
error-handling
trap
Mechaflash
fonte
fonte
bashdb
. Parece que o primeiro argumento paratrap
pode conter variáveis que são avaliadas no contexto desejado. Entãotrap 'echo $LINENO' ERR'
deve funcionar.trap 'echo $LINENO' ERR
. O primeiro argumento paratrap
é todo oecho $LINENO
texto citado. Isso está no bash.trap 'echo $LINENO' ERR
, com aspas simples, não aspas duplas. Com o comando que você escreveu,$LINENO
é expandido quando a linha 2 é analisada, de modo que a interceptação éecho 2
(ou melhorECHO 2
, qual seria a saídabash: ECHO: command not found
).Respostas:
Como indicado nos comentários, sua citação está errada. Você precisa de aspas simples para impedir que
$LINENO
seja expandida quando a linha de interceptação for analisada pela primeira vez.Isso funciona:
Executando:
fonte
echo hello | grep foo
não parece lançar erro para mim. Estou entendendo mal alguma coisa?grep
, o status de saída é 0 se houver uma correspondência, 1 se não houver correspondência e> 1 para um erro. Você pode verificar o comportamento em seu sistema comecho hello | grep foo; echo $?
Você também pode usar o 'chamador' do bash:
também imprime o nome do arquivo:
fonte
Eu realmente gosto da resposta dada pelo @Mat acima. Com base nisso, escrevi um pequeno auxiliar que fornece um pouco mais de contexto para o erro:
Podemos inspecionar o script para a linha que causou a falha:
Aqui está um pequeno script de teste:
Quando executamos, obtemos:
fonte
$(caller)
os dados de para fornecer o contexto, mesmo que a falha não esteja no script atual, mas em uma de suas importações. Muito bom!Inspirado em outra resposta, aqui está um manipulador de erros contextuais mais simples:
Você também pode usar awk em vez de cauda e cabeça, se necessário.
fonte
Aqui está outra versão, inspirada em @sanmai e @unpythonic. Ele mostra as linhas de script em torno do erro, com os números das linhas e o status da saída - usando tail & head como parece mais simples que a solução awk.
Mostrando isso como duas linhas aqui para facilitar a leitura - você pode unir essas linhas em uma, se preferir (preservando o
;
):Isso funciona muito bem com
set -euo pipefail
( modo estrito não oficial ) - qualquer erro variável indefinido fornece um número de linha sem disparar oERR
pseudo-sinal, mas os outros casos mostram o contexto.Exemplo de saída:
fonte
Sim,
LINENO
e asBASH_LINENO
variáveis são úteis para obter a linha de falha e as linhas que levam a ela.Não, apenas falta a
-q
opção com grep ...... Com a
-q
opçãogrep
retornará0
paratrue
e1
parafalse
. E em Bash étrap
nãoTrap
...Aqui está um captador que você pode achar útil para depurar coisas que têm um pouco mais de complexidade ciclomática ...
failure.sh
... e um exemplo de script de uso para expor as diferenças sutis de como definir a interceptação acima também para o rastreamento de funções ...
example_usage.sh
O exemplo acima foi testado no Bash versão 4+, portanto, deixe um comentário se for necessário algo para versões anteriores ao quatro ou Abra um problema se ele não detectar falhas nos sistemas com uma versão mínima de quatro.
Os principais tópicos são ...
-E
faz com que erros nas funções borbulhem-o functrace
causas permite mais verbosidade quando algo dentro de uma função falhaAspas simples são usadas em torno da chamada de função e as aspas duplas em torno de argumentos individuais
Referências
LINENO
eBASH_LINENO
são passadas em vez dos valores atuais, embora isso possa ser abreviado em versões posteriores do vinculado à interceptação, de modo que a linha de falha final chegue à saídaOs valores de
BASH_COMMAND
e exit status ($?
) são passados, primeiro para obter o comando que retornou um erro e, segundo, para garantir que a interceptação não seja acionada em status de não erroE enquanto outros podem discordar, acho mais fácil criar uma matriz de saída e usar printf para imprimir cada elemento da matriz em sua própria linha ...
... também o
>&2
bit no final faz com que os erros cheguem aonde deveriam (erro padrão) e permite capturar apenas erros ...Conforme mostrado por esses e outros exemplos no Stack Overflow, existem várias maneiras de criar um auxiliar de depuração usando utilitários embutidos.
fonte