Menjalankan exitsubkulit adalah satu perangkap:
#!/bin/bash
function calc { echo 42; exit 1; }
echo $(calc)
Script mencetak 42, keluar dari subkulit dengan kode kembali 1, dan melanjutkan dengan skrip. Bahkan mengganti panggilan dengan echo $(CALC) || exit 1tidak membantu karena kode balik echoadalah 0 terlepas dari kode balik calc. Dan calcdieksekusi sebelum echo.
Yang lebih membingungkan adalah menggagalkan efek exitdengan membungkusnya menjadi localbuiltin seperti pada script berikut. Saya tersandung masalah ketika saya menulis fungsi untuk memverifikasi nilai input. Contoh:
Saya ingin membuat file bernama "year month day.log", yaitu 20141211.loguntuk hari ini. Tanggal tersebut diinput oleh pengguna yang mungkin gagal memberikan nilai wajar. Oleh karena itu, dalam fungsi saya, fnamesaya memeriksa nilai balik dateuntuk memverifikasi validitas input pengguna:
#!/bin/bash
doit ()
{
local FNAME=$(fname "$1") || exit 1
touch "${FNAME}"
}
fname ()
{
date +"%Y%m%d.log" -d"$1" 2>/dev/null
if [ "$?" != 0 ] ; then
echo "fname reports \"Illegal Date\"" >&2
exit 1
fi
}
doit "$1"
Kelihatan bagus. Biarkan skrip diberi nama s.sh. Jika pengguna memanggil skrip ./s.sh "Thu Dec 11 20:45:49 CET 2014", file 20141211.logdibuat. Namun, jika tipe pengguna ./s.sh "Thu hec 11 20:45:49 CET 2014", maka skrip menghasilkan:
fname reports "Illegal Date"
touch: cannot touch ‘’: No such file or directory
Baris fname…mengatakan bahwa data input buruk telah terdeteksi di subkulit. Tetapi exit 1pada akhir local …baris tidak pernah dipicu karena localarahan selalu kembali 0. Ini karena localdieksekusi setelah $(fname) dan dengan demikian menimpa kode kembali. Dan karena itu, skrip berlanjut dan memanggil touchdengan parameter kosong. Contoh ini sederhana tetapi perilaku bash bisa sangat membingungkan dalam aplikasi nyata. Saya tahu, programmer sebenarnya tidak menggunakan penduduk setempat
Untuk memperjelas: Tanpa local, skrip dibatalkan seperti yang diharapkan ketika tanggal yang tidak valid dimasukkan.
Cara mengatasinya adalah dengan membagi garis seperti
local FNAME
FNAME=$(fname "$1") || exit 1
Perilaku aneh sesuai dengan dokumentasi localdi dalam halaman manual bash: "Status pengembalian adalah 0 kecuali lokal digunakan di luar fungsi, nama tidak valid diberikan, atau nama adalah variabel readonly."
Meskipun bukan bug, saya merasa bahwa perilaku bash adalah berlawanan dengan intuisi. Saya menyadari urutan eksekusi, localtidak harus menutupi tugas yang rusak, namun.
Jawaban awal saya berisi beberapa ketidaktepatan. Setelah diskusi yang mendalam dan mendalam dengan mikeserv (terima kasih untuk itu) saya pergi untuk memperbaikinya.