I'm mempelajari kandungan ini preinst file script yang mengeksekusi sebelum paket itu dibongkar dari arsip Debian (.deb) file.
Script kode berikut:
#!/bin/bash
set -e
# Automatically added by dh_installinit
if [ "$1" = install ]; then
if [ -d /usr/share/MyApplicationName ]; then
echo "MyApplicationName is just installed"
return 1
fi
rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf
rm -Rf $HOME/.local/share/file-manager/actions/*
fi
# End automatically added section
Permintaan pertama saya adalah tentang garis:
set -e
Saya berpikir bahwa sisa dari script ini cukup sederhana: Itu cek apakah Debian/Ubuntu paket manajer adalah pelaksana instalasi operasi. Jika sudah, cek apakah aplikasi yang telah diinstal pada sistem. Jika memiliki, script cetak pesan "MyApplicationName hanya dipasang" dan berakhir (kembali 1
berarti yang berakhir dengan sebuah "kesalahan", bukan?).
Jika pengguna meminta Debian/Ubuntu sistem paket untuk menginstal paket saya, script juga menghapus dua direktori.
Apakah ini benar atau aku kehilangan sesuatu?
Dari membantu
:
-e Exit immediately if a command exits with a non-zero status.
Tapi itu's dianggap praktek yang buruk oleh beberapa (bash FAQ dan irc freenode #bash FAQ penulis). It's dianjurkan untuk menggunakan:
trap 'do_something' ERR
untuk menjalankan do_something
fungsi ketika terjadi kesalahan.
untuk e
menghentikan eksekusi dari script jika perintah atau pipa memiliki kesalahan - yang merupakan kebalikan dari shell default perilaku, yang adalah untuk mengabaikan kesalahan dalam script. Type help set
di terminal untuk melihat dokumentasi untuk ini built-in perintah.
Sebagai per bash - Set Builtin manual, jika -e
/errexit
diatur, shell keluar segera jika pipeline terdiri dari satu perintah sederhana, daftar atau senyawa perintah kembali non-zero status.
Secara default, status keluar dari sebuah pipa adalah exit status dari perintah terakhir dalam pipa, kecuali pipefail
pilihan diaktifkan (it's dinonaktifkan secara default).
Jika demikian, pipa's kembali status terakhir (paling kanan) perintah untuk keluar dengan non-zero status, atau nol jika semua perintah exit berhasil.
Jika anda'd seperti untuk mengeksekusi sesuatu pada keluar, mencoba mendefinisikan trap
, misalnya:
trap onexit EXIT
di mana onexit
adalah fungsi untuk melakukan sesuatu yang pada keluar, seperti di bawah ini yang merupakan percetakan sederhana stack trace:
onexit(){ while caller $((n++)); do :; done; }
Ada pilihan yang sama -E
/errtrace
yang akan menjebak pada ERR sebaliknya, misalnya:
trap onerr ERR
Status nol contoh:
$ true; echo $?
0
Non-status nol contoh:
$ false; echo $?
1
Meniadakan status contoh:
$ ! false; echo $?
0
$ false || true; echo $?
0
Tes dengan pipefail
dinonaktifkan:
$ bash -c 'set +o pipefail -e; true | true | true; echo success'; echo $?
success
0
$ bash -c 'set +o pipefail -e; false | false | true; echo success'; echo $?
success
0
$ bash -c 'set +o pipefail -e; true | true | false; echo success'; echo $?
1
Tes dengan pipefail
yang diaktifkan:
$ bash -c 'set -o pipefail -e; true | false | true; echo success'; echo $?
1
Saya menemukan pertanyaan ini saat Googling, mencoba untuk mencari tahu apa exit status adalah sebuah script yang dibatalkan karena set-e
. Jawabannya tidak't muncul jelas kepada saya, maka jawaban ini. Pada dasarnya, set-e
membatalkan eksekusi perintah (misalnya shell script) dan mengembalikan status keluar kode perintah yang gagal (yaitu dalam naskah, tidak luar script).
Sebagai contoh, misalkan saya memiliki sebuah shell script outer-test.sh
:
#!/bin/sh
set -e
./inner-test.sh
exit 62;
Kode untuk inner-test.sh
adalah:
#!/bin/sh
exit 26;
Ketika saya menjalankan outer-script.sh
dari baris perintah saya luar skrip berakhir dengan kode keluar dari dalam script:
$ ./outer-test.sh
$ echo $?
26
Saya percaya niat untuk script di pertanyaan untuk gagal dengan cepat.
Untuk tes ini sendiri, cukup ketik set-e
pada bash prompt. Sekarang, coba jalankan ls
. Anda'll mendapatkan daftar direktori. Sekarang, ketik lsd
. Bahwa perintah ini tidak diakui dan akan kembali kode kesalahan, dan sehingga anda bash prompt akan menutup (karena untuk e
).
Sekarang, untuk memahami ini dalam konteks 'script', menggunakan script sederhana ini:
#!/bin/bash
# set -e
lsd
ls
Jika anda menjalankannya seperti ini, anda'll mendapatkan daftar direktori dari ls
pada baris terakhir. Jika anda tanda komentar untuk e
dan berlari lagi, anda tidak't melihat daftar direktori sebagai bash berhenti pengolahan sekali itu kesalahan dari lsd
.
Ini adalah pertanyaan lama, tapi tidak ada jawaban di sini membahas penggunaan set-e
alias set-o errexit
dalam paket Debian penanganan script. Penggunaan opsi ini wajib dalam script ini, per Debian policy; maksud rupanya untuk menghindari kemungkinan error yang tidak tertangani kondisi.
Apa artinya ini dalam praktek adalah bahwa anda harus memahami dalam kondisi apa perintah yang anda jalankan bisa kembali kesalahan, dan menangani setiap kesalahan-kesalahan secara eksplisit.
Umum gotchas misalnya diff
(kembali kesalahan ketika ada perbedaan) dan grep
(kembali kesalahan ketika tidak ada pertandingan). Anda dapat menghindari kesalahan-kesalahan yang dengan eksplisit penanganan:
diff this that ||
echo "$0: there was a difference" >&2
grep cat food ||
echo "$0: no cat in the food" >&2
(Perhatikan juga bagaimana kita berhati-hati untuk memasukkan script saat ini's nama di pesan, dan menulis pesan diagnostik standar kesalahan bukan standar output.)
Jika tidak ada eksplisit penanganan adalah benar-benar diperlukan atau berguna, secara eksplisit melakukan apa-apa:
diff this that || true
grep cat food || :
(Penggunaan shell's :
no-op perintah ini sedikit tidak jelas, tapi cukup sering terlihat.)
Hanya untuk mengulangi,
something || other
adalah singkatan untuk
if something; then
: nothing
else
other
fi
yaitu kita secara eksplisit mengatakan lain
harus berjalan jika dan hanya jika sesuatu
gagal. Dengan tulisan tangan jika
(dan lain shell kontrol aliran pernyataan seperti sementara
, sampai
) adalah juga cara yang sah untuk menangani kesalahan (memang, jika bukan't, shell script dengan set-e
tidak pernah bisa mengandung kontrol aliran pernyataan!)
Dan juga, hanya untuk menjadi eksplisit, tidak adanya penanganan seperti ini, set-e
akan menyebabkan seluruh script untuk segera gagal dengan pesan kesalahan jika diff
ditemukan perbedaan, atau jika grep
didn't menemukan kecocokan.
Di sisi lain, beberapa perintah don't menghasilkan kesalahan status keluaran: bila anda'd ingin mereka. Sering bermasalah perintah menemukan
(exit status tidak mencerminkan apakah file yang benar-benar ditemukan) dan sed
(exit status won't mengungkapkan apakah script menerima masukan atau benar-benar dilakukan setiap perintah berhasil). Sederhana penjaga dalam beberapa skenario adalah untuk pipa untuk perintah yang tidak berteriak jika tidak ada output:
find things | grep .
sed -e 's/o/me/' stuff | grep ^
Perlu dicatat bahwa status keluar dari sebuah pipa adalah exit status dari perintah terakhir dalam pipa. Jadi perintah di atas benar-benar benar-benar menutupi status menemukan
dan sed
, dan hanya memberitahu anda apakah grep
akhirnya berhasil.
(Bash, tentu saja, memiliki set-o pipefail
; tapi paket Debian script tidak dapat menggunakan Bash fitur. Kebijakan tegas menyatakan penggunaan POSIX sh
untuk script ini, meskipun ini tidak selalu terjadi.)
Dalam banyak situasi, ini adalah sesuatu yang terpisah watch out untuk saat coding membela diri. Kadang-kadang anda harus misalnya pergi melalui sementara file sehingga anda dapat melihat apakah perintah yang menghasilkan output yang berhasil selesai, bahkan ketika idiom dan kenyamanan sebaliknya akan mengarahkan anda untuk menggunakan shell pipa.
Script 1: without setting -e
#!/bin/bash
decho "hi"
echo "hello"
This will throw error in decho and program continuous to next line
Script 2: With setting -e
#!/bin/bash
set -e
decho "hi"
echo "hello"
# Up to decho "hi" shell will process and program exit, it will not proceed further