Saya ingin memunculkan kesalahan dalam skrip Bash dengan pesan "Kasus uji Gagal !!!". Bagaimana melakukan ini di Bash?
Sebagai contoh:
if [ condition ]; then
raise error "Test cases failed !!!"
fi
linux
bash
shell
error-handling
Naveen Kumar
sumber
sumber
echo you screwed up at ... | mail -s BUG $bugtrackeremailaddress
?Jawaban:
Ini tergantung di mana Anda ingin pesan kesalahan disimpan.
Anda dapat melakukan hal berikut:
Atau berikut ini:
Ketika Anda mengajukan pengecualian, Anda menghentikan eksekusi program.
Anda juga dapat menggunakan sesuatu seperti di
exit xxx
manaxxx
kode kesalahan yang mungkin ingin Anda kembalikan ke sistem operasi (dari 0 hingga 255). Ini125
dan64
hanya kode acak yang dapat Anda gunakan untuk keluar. Saat Anda perlu menunjukkan ke OS bahwa program berhenti secara tidak normal (mis. Terjadi kesalahan), Anda harus meneruskan kode keluar bukan nol keexit
.Seperti yang ditunjukkan oleh @chepner , Anda bisa melakukannya
exit 1
, yang berarti kesalahan yang tidak ditentukan .sumber
1>&2
akan melakukan trikexit
dengan sendirinya menggunakan status keluar dari perintah yang terakhir diselesaikan, yang mungkin 0.exit 1
, yang menurut konvensi berarti kesalahan yang tidak ditentukan.Penanganan kesalahan dasar
Jika runner kasus pengujian Anda mengembalikan kode bukan nol untuk pengujian yang gagal, Anda cukup menulis:
Atau bahkan lebih pendek:
Atau yang terpendek:
Untuk keluar dengan kode keluar test_handler:
Penanganan kesalahan lanjutan
Jika Anda ingin mengambil pendekatan yang lebih komprehensif, Anda dapat memiliki penangan kesalahan:
lalu panggil setelah menjalankan kasus uji Anda:
atau
Keuntungan memiliki penangan kesalahan
exit_if_error
adalah:if
blok yang menguji kode keluar untuk kesalahanPenanganan kesalahan dan pencatatan perpustakaan
Berikut implementasi lengkap penanganan error dan logging:
https://github.com/codeforester/base/blob/master/lib/stdlib.sh
Pos terkait
__FILE__
,__LINE__
di Bashsumber
Ada beberapa cara lain untuk mengatasi masalah ini. Dengan asumsi salah satu persyaratan Anda adalah menjalankan skrip / fungsi shell yang berisi beberapa perintah shell dan memeriksa apakah skrip berhasil berjalan dan menampilkan kesalahan jika terjadi kegagalan.
Perintah shell pada umumnya mengandalkan kode keluar yang dikembalikan untuk memberi tahu shell jika berhasil atau gagal karena beberapa kejadian tak terduga.
Jadi apa yang ingin Anda lakukan termasuk dalam dua kategori ini
Bergantung pada mana yang ingin Anda lakukan, ada opsi shell yang tersedia untuk digunakan. Untuk kasus pertama, shell menyediakan opsi dengan
set -e
dan untuk kasus kedua Anda bisa melakukantrap
onEXIT
Haruskah saya gunakan
exit
dalam skrip / fungsi saya?Menggunakan
exit
secara umum meningkatkan keterbacaan Dalam rutinitas tertentu, setelah Anda mengetahui jawabannya, Anda ingin segera keluar dari rutinitas panggilan. Jika rutinitas didefinisikan sedemikian rupa sehingga tidak memerlukan pembersihan lebih lanjut setelah mendeteksi kesalahan, tidak segera keluar berarti Anda harus menulis lebih banyak kode.Jadi dalam kasus jika Anda perlu melakukan tindakan pembersihan pada skrip untuk membuat penghentian skrip bersih, lebih disukai untuk tidak menggunakan
exit
.Haruskah saya gunakan
set -e
untuk kesalahan saat keluar?set -e
adalah upaya untuk menambahkan "deteksi kesalahan otomatis" ke shell. Tujuannya adalah untuk membatalkan shell setiap kali terjadi kesalahan, tetapi ia datang dengan banyak potensi jebakan misalnya,Perintah yang merupakan bagian dari tes if kebal. Dalam contoh, jika Anda mengharapkannya untuk merusak
test
pemeriksaan pada direktori yang tidak ada, itu tidak akan terjadi, itu akan masuk ke kondisi lainPerintah dalam pipa selain yang terakhir, kebal. Dalam contoh di bawah ini, karena kode keluar perintah yang paling baru dijalankan (paling kanan) dianggap (
cat
) dan berhasil. Ini dapat dihindari dengan menetapkanset -o pipefail
opsi tetapi ini masih peringatan.Direkomendasikan untuk digunakan -
trap
saat keluarPutusannya adalah jika Anda ingin menangani kesalahan alih-alih keluar secara membabi buta, alih-alih menggunakan
set -e
, gunakan atrap
padaERR
sinyal pseudo.The
ERR
perangkap tidak untuk menjalankan kode ketika shell itu sendiri keluar dengan nol non kode kesalahan, tetapi ketika perintah dijalankan oleh yang shell yang bukan merupakan bagian dari kondisi (seperti di jikacmd
, ataucmd ||
) keluar dengan status keluar non-zero .Praktik umumnya adalah kita mendefinisikan penangan perangkap untuk memberikan informasi debug tambahan pada baris mana dan apa yang menyebabkan keluar. Ingat kode keluar dari perintah terakhir yang menyebabkan
ERR
sinyal masih tersedia pada saat ini.dan kami hanya menggunakan handler ini seperti di bawah ini di atas skrip yang gagal
Menyatukan ini pada skrip sederhana yang terdapat
false
pada baris 15, informasi yang akan Anda peroleh sebagaiThe
trap
juga menyediakan pilihan terlepas dari kesalahan hanya menjalankan pembersihan pada shell selesai (misalnya Anda keluar shell script), pada sinyalEXIT
. Anda juga dapat menangkap banyak sinyal pada saat yang bersamaan. Daftar sinyal yang didukung untuk melakukan trap dapat ditemukan pada halaman manual trap.1p - LinuxHal lain yang perlu diperhatikan adalah memahami bahwa tidak ada metode yang disediakan yang berfungsi jika Anda berurusan dengan sub-shell yang terlibat dalam hal ini, Anda mungkin perlu menambahkan penanganan kesalahan Anda sendiri.
Pada sub-shell dengan
set -e
tidak akan berfungsi. Itufalse
dibatasi untuk sub-shell dan tidak pernah disebarkan ke shell induk. Untuk melakukan penanganan kesalahan di sini, tambahkan logika Anda sendiri yang harus dilakukan(false) || false
Hal yang sama
trap
juga terjadi dengan . Logika di bawah ini tidak akan berfungsi karena alasan yang disebutkan di atas.sumber
Berikut adalah jebakan sederhana yang mencetak argumen terakhir dari apa pun yang gagal ke STDERR, melaporkan baris yang gagal, dan keluar dari skrip dengan nomor baris sebagai kode keluar. Perhatikan bahwa ini tidak selalu merupakan ide bagus, tetapi ini menunjukkan beberapa aplikasi kreatif yang dapat Anda kembangkan.
Saya memasukkannya ke dalam skrip dengan loop untuk mengujinya. Saya hanya memeriksa hit pada beberapa nomor acak; Anda mungkin menggunakan tes yang sebenarnya. Jika saya perlu jaminan, saya sebut salah (yang memicu jebakan) dengan pesan yang ingin saya lempar.
Untuk fungsionalitas yang dielaborasi, buatlah panggilan trap sebagai fungsi pemrosesan. Anda selalu dapat menggunakan pernyataan kasus pada arg ($ _) jika Anda perlu melakukan lebih banyak pembersihan, dll. Tetapkan ke var untuk mendapatkan sedikit gula sintaksis -
Output sampel:
Jelas, Anda bisa
Banyak ruang untuk perbaikan desain.
Kelemahannya termasuk fakta bahwa
false
tidak cantik (dengan demikian gula), dan hal-hal lain yang tersandung perangkap mungkin terlihat sedikit bodoh. Tetap saja, saya suka metode ini.sumber
Anda memiliki 2 opsi: Alihkan output skrip ke file, Perkenalkan file log di skrip dan
Di sini Anda berasumsi bahwa skrip mengeluarkan semua info yang diperlukan, termasuk peringatan dan pesan kesalahan. Anda kemudian dapat mengarahkan output ke file pilihan Anda.
Perintah di atas mengalihkan baik keluaran standar dan keluaran kesalahan ke file log Anda.
Dengan menggunakan pendekatan ini, Anda tidak perlu memasukkan file log ke dalam skrip, sehingga logikanya sedikit lebih mudah.
Dalam skrip Anda, tambahkan file log baik dengan mengkodekannya secara keras:
atau meneruskannya dengan parameter:
Sebaiknya tambahkan stempel waktu pada saat eksekusi ke file log di bagian atas skrip:
Anda kemudian dapat mengarahkan pesan kesalahan Anda ke file log
Ini akan menambahkan kesalahan ke file log dan melanjutkan eksekusi. Jika Anda ingin menghentikan eksekusi saat terjadi kesalahan kritis, Anda bisa
exit
skrip:Catat itu
exit 1
menunjukkan bahwa program menghentikan eksekusi karena kesalahan yang tidak ditentukan. Anda dapat menyesuaikan ini jika Anda suka.Dengan menggunakan pendekatan ini, Anda dapat menyesuaikan log Anda dan memiliki file log yang berbeda untuk setiap komponen skrip Anda.
Jika Anda memiliki skrip yang relatif kecil atau ingin mengeksekusi skrip orang lain tanpa mengubahnya, pendekatan pertama lebih cocok.
Jika Anda selalu ingin file log berada di lokasi yang sama, ini adalah opsi yang lebih baik dari 2. Juga jika Anda telah membuat skrip besar dengan banyak komponen maka Anda mungkin ingin membuat log setiap bagian secara berbeda dan pendekatan kedua adalah satu-satunya pilihan.
sumber
Saya sering merasa berguna untuk menulis fungsi untuk menangani pesan kesalahan sehingga kodenya lebih bersih secara keseluruhan.
Ini mengambil kode kesalahan dari perintah sebelumnya dan menggunakannya sebagai kode kesalahan default saat keluar dari seluruh skrip. Ini juga mencatat waktu, dengan mikrodetik yang didukung (tanggal GNU
%N
adalah nanodetik, yang kami potong menjadi mikrodetik nanti).Jika opsi pertama adalah nol atau bilangan bulat positif, itu menjadi kode keluar dan kami menghapusnya dari daftar opsi. Kami kemudian melaporkan pesan ke kesalahan standar, dengan nama skrip, kata "ERROR", dan waktu (kami menggunakan perluasan parameter untuk memotong nanodetik menjadi mikrodetik, atau untuk waktu non-GNU, untuk memotong misalnya
12:34:56.%N
ke12:34:56
). Titik dua dan spasi ditambahkan setelah kata ERROR, tetapi hanya jika ada pesan kesalahan yang diberikan. Terakhir, kami keluar dari skrip menggunakan kode keluar yang telah ditentukan sebelumnya, memicu jebakan seperti biasa.Beberapa contoh (asumsikan kode tetap ada
script.sh
):sumber