Saya mencoba membuat beberapa pelaporan kesalahan menggunakan Perangkap untuk memanggil fungsi pada semua kesalahan:
Trap "_func" ERR
Apakah mungkin untuk mendapatkan saluran dari mana sinyal ERR dikirim? Shell itu bash.
Jika saya melakukan itu, saya bisa membaca dan melaporkan perintah apa yang digunakan dan mencatat / melakukan beberapa tindakan.
Atau mungkin saya salah dalam hal ini?
Saya diuji dengan yang berikut:
#!/bin/bash
trap "ECHO $LINENO" ERR
echo hello | grep "asdf"
Dan $LINENO
kembali 2. Tidak bekerja.
bash
shell-script
error-handling
trap
Mechaflash
sumber
sumber
bashdb
. Tampaknya argumen pertama untuktrap
dapat berisi variabel yang dievaluasi dalam konteks yang diinginkan. Jaditrap 'echo $LINENO' ERR'
harusnya bekerja.trap 'echo $LINENO' ERR
. Argumen pertamatrap
adalah seluruhecho $LINENO
hardquoted. Ini dalam bash.trap 'echo $LINENO' ERR
, dengan tanda kutip tunggal, bukan tanda kutip ganda. Dengan perintah yang Anda tulis,$LINENO
diperluas ketika baris 2 diuraikan, jadi jebakannya adalahecho 2
(atau lebih tepatnyaECHO 2
, yang akan ditampilkanbash: ECHO: command not found
).Jawaban:
Seperti yang ditunjukkan dalam komentar, penawaran Anda salah. Anda perlu satu tanda kutip untuk mencegah
$LINENO
agar tidak diperluas ketika garis perangkap pertama kali diuraikan.Ini bekerja:
Menjalankannya:
sumber
echo hello | grep foo
sepertinya tidak menimbulkan kesalahan bagi saya. Apakah saya salah memahami sesuatu?grep
memiliki status keluar 0 jika ada kecocokan, 1 jika tidak ada kecocokan dan> 1 untuk kesalahan. Anda dapat memeriksa perilaku di sistem Anda denganecho hello | grep foo; echo $?
Anda juga dapat menggunakan bash builtin 'pemanggil':
itu mencetak nama file juga:
sumber
Saya sangat suka jawaban yang diberikan oleh @Mat di atas. Membangun ini, saya menulis sedikit pembantu yang memberikan sedikit lebih banyak konteks untuk kesalahan:
Kita dapat memeriksa skrip untuk baris yang menyebabkan kegagalan:
Ini dia dalam skrip tes kecil:
Saat kami menjalankannya, kami dapat:
sumber
$(caller)
data untuk memberikan konteks bahkan jika kegagalan tidak ada dalam skrip saat ini tetapi salah satu dari impornya. Sangat bagus!Terinspirasi oleh jawaban lain, berikut ini adalah penangan kesalahan kontekstual yang lebih sederhana:
Anda juga dapat menggunakan awk sebagai ganti tail & head jika diperlukan.
sumber
Ini versi lain, terinspirasi oleh @sanmai dan @unpythonic. Ini menunjukkan garis skrip di sekitar kesalahan, dengan nomor baris, dan status keluar - menggunakan tail & head karena tampaknya lebih sederhana daripada solusi awk.
Menampilkan ini sebagai dua baris di sini agar mudah dibaca - Anda dapat menggabungkannya menjadi satu jika Anda lebih suka (menjaga
;
):Ini bekerja cukup baik dengan
set -euo pipefail
( mode ketat tidak resmi ) - setiap kesalahan variabel yang tidak terdefinisi memberikan nomor baris tanpa menembakkanERR
sinyal semu, tetapi kasus lain menunjukkan konteks.Contoh output:
sumber
Ya,
LINENO
danBASH_LINENO
variabel sangat berguna untuk mendapatkan garis kegagalan dan garis yang mengarah ke sana.Tidak, hanya
-q
opsi yang hilang dengan ...... Dengan
-q
opsigrep
akan kembali0
untuktrue
dan1
untukfalse
. Dan di Bash itutrap
bukanTrap
...Ini adalah penjebak yang mungkin berguna untuk men-debug hal-hal yang memiliki kompleksitas siklomatik sedikit lebih ...
failure.sh
... dan contoh skrip penggunaan untuk mengungkap perbedaan halus dalam cara mengatur jebakan di atas untuk penelusuran fungsi juga ...
example_usage.sh
Di atas di mana diuji pada Bash versi 4+, jadi tinggalkan komentar jika sesuatu untuk versi sebelum empat diperlukan, atau Buka Masalah jika gagal menjebak kegagalan pada sistem dengan versi minimum empat.
Takeaways utama adalah ...
-E
menyebabkan kesalahan dalam fungsi muncul-o functrace
sebab memungkinkan lebih banyak verbositas ketika sesuatu dalam suatu fungsi gagalKutipan tunggal digunakan di sekitar pemanggilan fungsi dan kutipan ganda di sekitar argumen individual
Referensi ke
LINENO
danBASH_LINENO
diteruskan alih-alih nilai saat ini, meskipun ini mungkin disingkat di versi yang lebih baru terkait dengan perangkap, sehingga garis kegagalan akhir membuatnya menjadi outputNilai
BASH_COMMAND
dan status keluar ($?
) diteruskan, pertama untuk mendapatkan perintah yang mengembalikan kesalahan, dan kedua untuk memastikan bahwa jebakan tidak memicu status non-kesalahanDan sementara yang lain mungkin tidak setuju saya merasa lebih mudah untuk membangun array output dan menggunakan printf untuk mencetak setiap elemen array pada baris itu sendiri ...
... juga
>&2
sedikit di akhir menyebabkan kesalahan untuk pergi ke mana seharusnya (kesalahan standar), dan memungkinkan untuk menangkap kesalahan saja ...Seperti yang ditunjukkan oleh ini dan contoh-contoh lain pada Stack Overflow, ada banyak cara untuk membangun bantuan debugging menggunakan utilitas bawaan.
sumber