Bahasa yang tepat digunakan dalam spesifikasi UNIX Tunggal untuk menggambarkan artiset -e
adalah:
Ketika opsi ini aktif, jika perintah sederhana gagal karena salah satu alasan yang tercantum dalam Konsekuensi Kesalahan Shell atau mengembalikan nilai status keluar> 0, dan bukan [perintah kondisional atau negasi], maka shell akan segera keluar.
Ada ambiguitas tentang apa yang terjadi ketika perintah seperti itu terjadi dalam subkulit . Dari sudut pandang praktis, semua yang dapat dilakukan subshell adalah keluar dan mengembalikan status bukan nol ke shell induk. Apakah shell induk akan pada gilirannya keluar tergantung pada apakah status bukan nol ini diterjemahkan menjadi perintah sederhana yang gagal di shell induk.
Satu kasus bermasalah seperti itu adalah yang Anda temui: status pengembalian yang bukan nol dari substitusi perintah . Karena status ini diabaikan, itu tidak menyebabkan shell induk untuk keluar. Seperti yang sudah Anda temukan , cara untuk mengambil status keluar ke akun adalah dengan menggunakan substitusi perintah dalam penugasan sederhana : maka status keluar dari penugasan adalah status keluar dari substitusi perintah terakhir dalam penugasan .
Perhatikan bahwa ini akan berfungsi sebagaimana dimaksud hanya jika ada substitusi perintah tunggal, karena hanya status substitusi terakhir yang diperhitungkan. Misalnya, perintah berikut ini berhasil (baik sesuai dengan standar dan dalam setiap implementasi yang saya lihat):
a=$(false)$(echo foo)
Kasus lain yang harus diperhatikan adalah subshells eksplisit : (somecommand)
. Menurut interpretasi di atas, subshell dapat mengembalikan status bukan nol, tetapi karena ini bukan perintah sederhana di shell induk, shell induk harus melanjutkan. Faktanya, semua cangkang yang saya tahu membuat orang tua kembali pada saat ini. Meskipun ini berguna dalam banyak kasus seperti di (cd /some/dir && somecommand)
mana tanda kurung digunakan untuk menjaga operasi seperti perubahan direktori saat ini lokal, itu melanggar spesifikasi jika set -e
dimatikan dalam subkulit, atau jika subkulit mengembalikan status bukan nol dengan cara yang tidak akan menghentikannya, seperti menggunakan !
perintah yang benar. Misalnya, semua abu, bash, pdksh, ksh93, dan zsh keluar tanpa menampilkan foo
contoh berikut:
set -e; (set +e; false); echo "This should be displayed"
set -e; (! true); echo "This should be displayed"
Namun tidak ada perintah sederhana yang gagal saat set -e
diberlakukan!
Kasus bermasalah ketiga adalah elemen dalam pipa nontrivial . Dalam praktiknya, semua kerang mengabaikan kegagalan elemen-elemen pipa selain yang terakhir, dan menunjukkan salah satu dari dua perilaku mengenai elemen pipa terakhir:
- ATT ksh dan zsh, yang menjalankan elemen terakhir dari pipeline di shell induk, berbisnis seperti biasa: jika perintah sederhana gagal di elemen terakhir pipeline, shell mengeksekusi perintah itu, yang kebetulan adalah shell induk, keluar.
- Kerang lain memperkirakan perilaku dengan keluar jika elemen terakhir dari pipa mengembalikan status bukan nol.
Seperti sebelumnya, mematikan set -e
atau menggunakan negasi pada elemen terakhir dari pipa menyebabkannya mengembalikan status bukan-nol dengan cara yang seharusnya tidak menghentikan shell; kerang selain ATT ksh dan zsh akan keluar.
pipefail
Opsi Bash menyebabkan pipa keluar segera di bawah set -e
jika salah satu elemennya mengembalikan status bukan nol.
Perhatikan bahwa sebagai komplikasi lebih lanjut, bash dimatikan set -e
dalam subkulit kecuali dalam mode POSIX ( set -o posix
atau ada POSIXLY_CORRECT
di lingkungan saat bash dimulai).
Semua ini menunjukkan bahwa spesifikasi POSIX sayangnya melakukan pekerjaan yang buruk dalam menentukan -e
opsi. Untungnya, cangkang yang ada sebagian besar konsisten dalam perilaku mereka.