Místo použití vaší funkce bych místo toho použil tuto metodu:
$ 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"
Funguje to tak, že se zachytí chyba ERR a pak se zavolá failure()
funkce s aktuálním číslem řádku + příkaz bash, který byl proveden.
Příklad
Zde jsem se nestaral o vytváření souborů, f1
, f2
, f3
nebo f4
. Když spustím výše uvedený skript:
$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"
Selže a hlásí číslo řádku plus příkaz, který byl proveden.
Kromě LINENO
obsahující aktuální číslo řádku, je zde BASH_LINENO
a FUNCNAME
(a BASH_SOURCE
) pole obsahující názvy funkcí a čísla řádků, ze kterých jsou volány.
Takže můžete udělat něco takového:
#!/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
Spuštění, které by tisklo
'that thing' failed with exit code 123 in function 'foo' at line 9.
Pokud používáte set -e
nebo trap ... ERR
Chcete-li automaticky detekovat chyby, mějte na paměti, že mají určitá upozornění. Je také těžší zahrnout popis toho, co skript v té době dělal (jako vy ve vašem příkladu), i když to může být pro běžného uživatele užitečnější než jen číslo řádku.
Viz např. tyto pro problémy s set -e
a další:
- Proč sada -e nefunguje uvnitř podskořápek se závorkami () následovanými seznamem OR ||?
- bash -e se ukončí, když se let nebo expr vyhodnotí jako 0
- BashFAQ 105:Proč nastavení -e (nebo set -o errexit nebo past ERR) nedělá to, co jsem očekával?
Bash má vestavěnou proměnnou $LINENO
které je v příkazu nahrazeno aktuálním číslem řádku, takže můžete udělat
in_case_fail $? "at $LINENO: cp $file1 $file2"
Můžete také zkusit použít trap ... ERR
který se spustí, když příkaz selže (pokud není testován výsledek). Např.:
trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
Pak pokud příkaz jako cp $file1 $file2
selže, zobrazí se chybová zpráva s číslem řádku a ukončením. Příkaz také najdete chybně v proměnné $BASH_COMMAND
(i když ne žádná přesměrování atd.).