AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 462156
Accepted
yael
yael
Asked: 2018-08-13 09:18:54 +0800 CST2018-08-13 09:18:54 +0800 CST 2018-08-13 09:18:54 +0800 CST

Como encontro o número da linha no Bash quando ocorreu um erro?

  • 772

Como você encontra o número da linha no Bash onde ocorreu um erro?

Exemplo

Eu crio o seguinte script simples com números de linha para explicar o que precisamos. O script copiará os arquivos de

cp $file1 $file2
cp $file3 $file4

Quando um dos cpcomandos falhar, a função sairá com exit 1 . Queremos adicionar à função a capacidade de também imprimir o erro com o número da linha (por exemplo, 8 ou 12).

Isso é possível?

Exemplo de script

1 #!/bin/bash
2
3
4 function in_case_fail {
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6 }
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14
linux bash
  • 4 4 respostas
  • 22884 Views

4 respostas

  • Voted
  1. Best Answer
    slm
    2018-08-13T09:23:44+08:002018-08-13T09:23:44+08:00

    Em vez de usar sua função, eu usaria este método:

    $ cat yael.bash
    #!/bin/bash
    
    set -eE -o functrace
    
    file1=f1
    file2=f2
    file3=f3
    file4=f4
    
    failure() {
      local lineno=$1
      local msg=$2
      echo "Failed at $lineno: $msg"
    }
    trap 'failure ${LINENO} "$BASH_COMMAND"' ERR
    
    cp -- "$file1" "$file2"
    cp -- "$file3" "$file4"
    

    Isso funciona capturando o ERR e, em seguida, chamando a failure()função com o número da linha atual + comando bash que foi executado.

    Exemplo

    Aqui não tomei nenhum cuidado para criar os arquivos, f1, f2, f3, ou f4. Quando executo o script acima:

    $ ./yael.bash
    cp: cannot stat ‘f1’: No such file or directory
    Failed at 17: cp -- "$file1" "$file2"
    

    Ele falha, relatando o número da linha mais o comando que foi executado.

    • 52
  2. ilkkachu
    2018-08-13T11:00:23+08:002018-08-13T11:00:23+08:00

    Além de LINENOconter o número da linha atual, existem as matrizes BASH_LINENOand FUNCNAME(e BASH_SOURCE) que contêm os nomes das funções e os números das linhas de onde são chamadas.

    Então você poderia fazer algo assim:

    #!/bin/bash
    
    error() {
            printf "'%s' failed with exit code %d in function '%s' at line %d.\n" "${1-something}" "$?" "${FUNCNAME[1]}" "${BASH_LINENO[0]}"
    }
    
    foo() {
            ( exit   0 ) || error "this thing"
            ( exit 123 ) || error "that thing"
    }
    
    foo
    

    Executando isso imprimiria

    'that thing' failed with exit code 123 in function 'foo' at line 9.
    

    Se você usar set -e, ou trap ... ERRpara detectar erros automaticamente, observe que eles têm algumas ressalvas. Também é mais difícil incluir uma descrição do que o script estava fazendo no momento (como você fez no seu exemplo), embora isso possa ser mais útil para um usuário comum do que apenas o número da linha.

    Veja, por exemplo, estes para os problemas com set -ee outros:

    • Por que set -e não funciona dentro de subshells com parênteses () seguido por uma lista OR ||?
    • bash -e sai quando let ou expr é avaliado como 0
    • BashFAQ 105: Por que set -e (ou set -o errexit, ou trap ERR) não faz o que eu esperava?
    • 18
  3. meuh
    2018-08-13T10:22:12+08:002018-08-13T10:22:12+08:00

    Bash tem uma variável embutida $LINENOque é substituída pelo número da linha atual quando em uma instrução, então você pode fazer

    in_case_fail $? "at $LINENO: cp $file1 $file2"
    

    Você também pode tentar usar trap ... ERRo que é executado quando um comando falha (se o resultado não for testado). Por exemplo:

    trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
    

    Então, se um comando como cp $file1 $file2falhar, você receberá a mensagem de erro com o número da linha e uma saída. Você também encontrará o comando com erro na variável $BASH_COMMAND(embora não em qualquer redirecionamento, etc.).

    • 15
  4. iheggie
    2021-05-18T06:14:22+08:002021-05-18T06:14:22+08:00

    Eu decidi usar o seguinte, que inclui um rastreamento de pilha como list of fns [list of line numbers]se o script estivesse em uma função ou o número da linha do script caso contrário. Os agradecimentos também vão para as respostas anteriores, que expandi após algumas experiências para lidar com scripts baseados em fn e não baseados em fn.

    set -eE -o functrace
    
    failure() {
      local lineno=$2
      local fn=$3
      local exitstatus=$4
      local msg=$5
      local lineno_fns=${1% 0}
      if [[ "$lineno_fns" != "0" ]] ; then
        lineno="${lineno} ${lineno_fns}"
      fi
      echo "${BASH_SOURCE[1]}:${fn}[${lineno}] Failed with status ${exitstatus}: $msg"
    }
    trap 'failure "${BASH_LINENO[*]}" "$LINENO" "${FUNCNAME[*]:-script}" "$?" "$BASH_COMMAND"' ERR
    

    Então, uma simples falha de comando, se parece com:

    /tmp/b:script[32] Failed with status 1: cp fred john
    

    E funções aninhadas (onde hello1 chama hello2):

    /tmp/b:hello2 hello1 main[24 19 29] Failed with status 1: cp john 22
    

    Eu reporto o status de saída nos momentos estranhos em que ele fornece informações extras e, ao contrário de todos os outros, quero o nome do caminho completo do script.

    Mais trabalho será necessário para relatar a saída devido a sinais.

    • 2

relate perguntas

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Passe o sistema de arquivos raiz por rótulo para o kernel do Linux

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve