GNU/Linux >> Linux Esercitazione >  >> Linux

Come trovo il numero di riga in Bash quando si è verificato un errore?

Piuttosto che usare la tua funzione, userei invece questo metodo:

$ 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"

Funziona intrappolando su ERR e quindi chiamando failure() funzione con il numero di riga corrente + il comando bash che è stato eseguito.

Esempio

Qui non mi sono preoccupato di creare i file, f1 , f2 , f3 o f4 . Quando eseguo lo script precedente:

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

Fallisce, riportando il numero di riga più il comando che è stato eseguito.


Oltre a LINENO contenente il numero di riga corrente, ci sono i BASH_LINENO e FUNCNAME (e BASH_SOURCE ) che contengono i nomi delle funzioni e i numeri di riga da cui vengono chiamati.

Quindi potresti fare qualcosa del genere:

#!/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

L'esecuzione verrebbe stampata

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

Se usi set -e o trap ... ERR per rilevare automaticamente gli errori, tieni presente che hanno alcuni avvertimenti. È anche più difficile includere una descrizione di ciò che lo script stava facendo in quel momento (come hai fatto nel tuo esempio), anche se potrebbe essere più utile per un utente normale rispetto al semplice numero di riga.

Vedi ad es. questi per i problemi con set -e e altri:

  • Perché set -e non funziona all'interno di subshell con parentesi () seguite da un elenco OR ||?
  • bash -e esce quando let o expr restituisce 0
  • BashFAQ 105:Perché set -e (o set -o errexit o trap ERR) non fa quello che mi aspettavo?

Bash ha una variabile incorporata $LINENO che viene sostituito dal numero di riga corrente in un'istruzione, quindi puoi farlo

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

Puoi anche provare a usare trap ... ERR che viene eseguito quando un comando fallisce (se il risultato non è testato). Ad esempio:

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

Quindi se un comando come cp $file1 $file2 fallisce si otterrà il messaggio di errore con il numero di riga e un'uscita. Troverai anche il comando in errore nella variabile $BASH_COMMAND (sebbene non ci siano reindirizzamenti ecc.).


Linux
  1. Trovare file nella riga di comando (come fare per)

  2. Come trovare il numero di linee verticali disponibili nel terminal?

  3. Come leggere la penultima riga in un file usando Bash?

  4. Come posso contare il numero di caratteri in una variabile Bash

  5. Come impostare il colore del prompt dei comandi in Bash?

Come commentare in Bash

Come leggere un file riga per riga in Bash

Come trovare il numero di porta di un servizio in Linux

Come scoprire chi ha riavviato il sistema Linux e quando

Come trovare file sulla riga di comando di Ubuntu

Come cancellare il numero di riga in Vim durante la copia?