set -e
menghentikan skrip jika kode keluar yang bukan nol ditemukan, kecuali dalam kondisi tertentu. Untuk meringkas bahaya penggunaannya dalam beberapa kata: itu tidak berperilaku seperti yang orang pikirkan.
Menurut pendapat saya, itu harus dianggap sebagai peretasan berbahaya yang terus ada untuk tujuan kompatibilitas saja. The set -e
pernyataan tidak berubah shell dari bahasa yang menggunakan kode kesalahan ke dalam bahasa yang menggunakan aliran kontrol pengecualian-seperti, itu hanya buruk mencoba untuk meniru perilaku itu.
Greg Wooledge banyak bicara tentang bahaya set -e
:
Pada tautan kedua, ada berbagai contoh perilaku tidak intuitif dan tidak terduga set -e
.
Beberapa contoh perilaku tidak intuitif set -e
(beberapa diambil dari tautan wiki di atas):
set -e
x = 0
biarkan x ++
gema "x adalah $ x"
Hal di atas akan menyebabkan skrip shell keluar secara prematur, karena let x++
mengembalikan 0, yang diperlakukan oleh let
kata kunci sebagai nilai palsu dan berubah menjadi kode keluar yang tidak nol. set -e
pemberitahuan ini, dan diam-diam mengakhiri skrip.
set -e
[-d / opt / foo] && echo "Peringatan: foo sudah diinstal. Akan ditimpa." > & 2
gema "Memasang foo ..."
Di atas berfungsi seperti yang diharapkan, mencetak peringatan jika /opt/foo
sudah ada.
set -e
check_previous_install () {
[-d / opt / foo] && echo "Peringatan: foo sudah diinstal. Akan ditimpa." > & 2
}
periksa_previous_install
gema "Memasang foo ..."
Di atas, meskipun satu-satunya perbedaan adalah bahwa satu baris telah di refactored menjadi suatu fungsi, akan berakhir jika /opt/foo
tidak ada. Ini karena fakta bahwa itu bekerja pada awalnya adalah pengecualian khusus untuk set -e
perilaku. Saat a && b
mengembalikan nol, diabaikan oleh set -e
. Namun, sekarang karena fungsinya, kode keluar dari fungsi sama dengan kode keluar dari perintah itu, dan fungsi yang mengembalikan bukan nol akan secara diam-diam menghentikan skrip.
set -e
IFS = $ '\ n' baca -d '' -r -a config_vars <config
Di atas akan membaca array config_vars
dari file config
. Seperti yang mungkin dimaksudkan oleh penulis, itu berakhir dengan kesalahan jika config
hilang. Karena penulis mungkin tidak bermaksud, itu diam-diam berakhir jika config
tidak berakhir pada baris baru. Jika set -e
tidak digunakan di sini, maka config_vars
akan berisi semua baris file apakah itu berakhir pada baris baru atau tidak.
Pengguna Teks Sublime (dan editor teks lainnya yang menangani baris baru secara salah), berhati-hatilah.
set -e
should_audit_user () {
grup grup lokal = "$ (grup" $ 1 ")"
untuk grup dalam $ grup; melakukan
if ["$ group" = audit]; lalu kembalikan 0; fi
Selesai
kembali 1
}
if should_audit_user "$ user"; kemudian
logger 'Blah'
fi
Penulis di sini mungkin secara wajar berharap bahwa jika karena alasan tertentu pengguna $user
tidak ada, maka groups
perintah akan gagal dan skrip akan berhenti alih-alih membiarkan pengguna melakukan beberapa tugas tanpa diaudit. Namun, dalam hal ini set -e
pemutusan hubungan kerja tidak pernah berlaku. Jika $user
tidak dapat ditemukan karena alasan tertentu, alih-alih menghentikan skrip, should_audit_user
fungsi hanya akan mengembalikan data yang salah seolah-olah set -e
tidak berlaku.
Ini berlaku untuk fungsi apa pun yang dipanggil dari bagian kondisi if
pernyataan, tidak peduli seberapa dalam bersarang, di mana pun didefinisikan, tidak peduli bahkan jika Anda menjalankannya set -e
lagi. Penggunaan if
pada titik mana pun sepenuhnya menonaktifkan efek set -e
sampai blok kondisi sepenuhnya dieksekusi. Jika penulis tidak mengetahui jebakan ini, atau tidak tahu seluruh tumpukan panggilan mereka dalam semua situasi yang memungkinkan di mana suatu fungsi dapat dipanggil, maka mereka akan menulis kode kereta dan rasa aman palsu yang diberikan oleh set -e
akan setidaknya sebagian untuk menyalahkan.
Bahkan jika penulis sepenuhnya menyadari jebakan ini, solusinya adalah menulis kode dengan cara yang sama seperti orang akan menulisnya tanpa set -e
, secara efektif membuat pergantian yang kurang dari berguna; tidak hanya penulis harus menulis kode penanganan kesalahan manual seolah-olah set -e
tidak berlaku, tetapi kehadiran set -e
mungkin menipu mereka untuk berpikir bahwa mereka tidak perlu melakukannya.
Beberapa kelemahan lebih lanjut dari set -e
:
- Ini mendorong kode ceroboh. Penangan kesalahan benar-benar dilupakan, dengan harapan bahwa apa pun yang gagal akan melaporkan kesalahan dengan cara yang masuk akal. Namun, dengan contoh-contoh seperti di
let x++
atas, ini tidak terjadi. Jika skrip mati secara tak terduga, biasanya diam-diam, yang menghambat debugging. Jika skrip tidak mati dan Anda mengharapkannya (lihat poin sebelumnya), maka Anda memiliki bug yang lebih halus dan berbahaya di tangan Anda.
- Ini menuntun orang ke rasa aman yang salah. Lihat lagi
if
titik peluru -kondisi.
- Tempat di mana shell berakhir tidak konsisten antara versi shell atau shell. Dimungkinkan untuk secara tidak sengaja menulis skrip yang berperilaku berbeda pada versi bash yang lebih lama karena perilaku
set -e
tweak antara versi tersebut.
set -e
adalah masalah yang diperdebatkan, dan beberapa orang menyadari masalah di sekitarnya yang merekomendasikannya, sementara yang lain hanya merekomendasikan untuk berhati-hati saat aktif untuk mengetahui perangkapnya. Ada banyak pemula skrip shell yang merekomendasikan set -e
semua skrip sebagai catch-all untuk kondisi kesalahan, tetapi dalam kehidupan nyata itu tidak bekerja seperti itu.
set -e
bukan pengganti untuk pendidikan.