Daripada menggunakan fungsi Anda, saya akan menggunakan metode ini sebagai gantinya:
$ 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"
Ini berfungsi dengan menjebak ERR dan kemudian memanggil failure()
fungsi dengan nomor baris saat ini + perintah bash yang dijalankan.
Contoh
Di sini saya tidak terlalu berhati-hati dalam membuat file, f1
, f2
, f3
, atau f4
. Saat saya menjalankan skrip di atas:
$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"
Gagal, melaporkan nomor baris plus perintah yang dijalankan.
Selain LINENO
berisi nomor baris saat ini, ada BASH_LINENO
dan FUNCNAME
(dan BASH_SOURCE
) larik yang berisi nama fungsi dan nomor baris asal pemanggilannya.
Jadi Anda bisa melakukan sesuatu seperti ini:
#!/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
Menjalankan yang akan mencetak
'that thing' failed with exit code 123 in function 'foo' at line 9.
Jika Anda menggunakan set -e
, atau trap ... ERR
untuk mendeteksi kesalahan secara otomatis, perhatikan bahwa mereka memiliki beberapa peringatan. Juga lebih sulit untuk menyertakan deskripsi tentang apa yang dilakukan skrip pada saat itu (seperti yang Anda lakukan dalam contoh Anda), meskipun hal itu mungkin lebih berguna bagi pengguna biasa daripada sekadar nomor baris.
Lihat mis. ini untuk masalah dengan set -e
dan lainnya:
- Mengapa set -e tidak berfungsi di dalam subkulit dengan tanda kurung () diikuti oleh daftar OR ||?
- bash -e keluar saat let atau expr bernilai 0
- BashFAQ 105:Mengapa set -e (atau set -o errexit, atau trap ERR) tidak melakukan apa yang saya harapkan?
Bash memiliki variabel bawaan $LINENO
yang diganti dengan nomor baris saat ini saat dalam pernyataan, jadi Anda bisa melakukannya
in_case_fail $? "at $LINENO: cp $file1 $file2"
Anda juga dapat mencoba menggunakan trap ... ERR
yang berjalan saat perintah gagal (jika hasilnya tidak diuji). Misalnya:
trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
Kemudian jika perintah seperti cp $file1 $file2
gagal Anda akan mendapatkan pesan kesalahan dengan nomor baris dan keluar. Anda juga akan menemukan kesalahan perintah dalam variabel $BASH_COMMAND
(meskipun tidak ada pengalihan, dll.).