Saya sedang mempelajari konten dari file pertama ini yang dieksekusi oleh skrip sebelum paket tersebut dibuka dari file arsip Debian (.deb).
Script memiliki 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 baris:
set -e
Saya pikir sisa skripnya cukup sederhana: Memeriksa apakah manajer paket Debian / Ubuntu menjalankan operasi pemasangan. Jika ya, ia memeriksa apakah aplikasi saya baru saja diinstal pada sistem. Jika sudah, skrip mencetak pesan "MyApplicationName baru saja diinstal" dan berakhir ( return 1
artinya diakhiri dengan "kesalahan", bukan?).
Jika pengguna meminta sistem paket Debian / Ubuntu untuk menginstal paket saya, skrip juga menghapus dua direktori.
Apakah ini benar atau saya kehilangan sesuatu?
man set
set +e
Jawaban:
Dari
help set
:Tapi itu dianggap praktik buruk oleh beberapa (bash FAQ dan irc freenode #bash FAQ penulis). Disarankan untuk menggunakan:
untuk menjalankan
do_something
fungsi ketika terjadi kesalahan.Lihat http://mywiki.wooledge.org/BashFAQ/105
sumber
trap 'exit' ERR
ERR
perangkap tidak diwariskan oleh fungsi shell, jadi jika Anda memiliki fungsi,set -o errtrace
atauset -E
akan memungkinkan Anda untuk hanya mengatur perangkap sekali dan menerapkannya secara global.trap 'exit' ERR
melakukan apa-apa yang berbeda dariset -e
?set -e
menghentikan eksekusi skrip jika perintah atau pipa memiliki kesalahan - yang merupakan kebalikan dari perilaku shell default, yaitu mengabaikan kesalahan dalam skrip. Ketikhelp set
terminal untuk melihat dokumentasi untuk perintah bawaan ini.sumber
set -o pipefail
yang dapat digunakan untuk menyebarkan kesalahan sehingga nilai kembali dari perintah pipa tidak nol jika salah satu perintah sebelumnya keluar dengan status tidak nol.-o pipefail
hanya berarti bahwa status keluar dari perintah pertama yang bukan nol (mis. Kesalahan dalam-o errexit
hal) dari pipa disebarkan ke ujung. Perintah yang tersisa dalam pipa masih berjalan , bahkan denganset -o errexit
. Sebagai contoh:echo success | cat - <(echo piping); echo continues
, di manaecho success
merupakan, tetapi perintah keliru sukses, akan mencetaksuccess
,piping
dancontinues
, tetapifalse | cat - <(echo piping); echo continues
, denganfalse
mewakili perintah sekarang erroring diam-diam, masih akan mencetakpiping
sebelum keluar.Per bash - Manual Set Builtin , jika
-e
/errexit
diatur, shell segera keluar jika pipa yang terdiri dari satu perintah sederhana , daftar atau perintah gabungan mengembalikan status tidak nol.Secara default, status keluar dari pipa adalah status keluar dari perintah terakhir dalam pipa, kecuali jika
pipefail
opsi ini diaktifkan (dinonaktifkan secara default).Jika demikian, status pengembalian pipa dari perintah terakhir (paling kanan) untuk keluar dengan status bukan nol, atau nol jika semua perintah berhasil keluar.
Jika Anda ingin mengeksekusi sesuatu saat keluar, coba tentukan
trap
, misalnya:di mana
onexit
fungsi Anda untuk melakukan sesuatu saat keluar, seperti di bawah ini yang mencetak jejak tumpukan sederhana :Ada opsi serupa
-E
/errtrace
yang akan menjebak ERR sebagai gantinya, misalnya:Contohnya
Contoh status nol:
Contoh status bukan nol:
Contoh status yang dinegasikan:
Tes dengan
pipefail
dinonaktifkan:Tes dengan
pipefail
diaktifkan:sumber
Saya menemukan pos ini ketika mencoba mencari tahu apa status keluar untuk skrip yang dibatalkan karena a
set -e
. Jawabannya tidak tampak jelas bagi saya; karenanya jawaban ini. Pada dasarnya,set -e
batalkan eksekusi perintah (mis. Skrip shell) dan kembalikan kode status keluar dari perintah yang gagal (yaitu skrip dalam, bukan skrip luar) .Misalnya, saya punya skrip shell
outer-test.sh
:Kode untuk
inner-test.sh
adalah:Ketika saya menjalankan
outer-script.sh
dari baris perintah, skrip luar saya berakhir dengan kode keluar dari skrip dalam:sumber
Saya percaya maksudnya agar skrip yang dimaksud gagal cepat.
Untuk mengujinya sendiri, cukup ketik
set -e
bash prompt. Sekarang, coba jalankanls
. Anda akan mendapatkan daftar direktori. Sekarang, ketiklsd
. Perintah itu tidak dikenali dan akan mengembalikan kode kesalahan, sehingga bash prompt Anda akan ditutup (karenaset -e
).Sekarang, untuk memahami ini dalam konteks 'skrip', gunakan skrip sederhana ini:
Jika Anda menjalankannya apa adanya, Anda akan mendapatkan daftar direktori dari
ls
pada baris terakhir. Jika Anda menghapus tanda komentar padaset -e
dan menjalankan lagi, Anda tidak akan melihat daftar direktori sebagai bash berhenti diproses setelah menemui kesalahan darilsd
.sumber
Ini adalah pertanyaan lama, tetapi tidak ada jawaban di sini yang membahas penggunaan
set -e
aliasset -o errexit
dalam skrip penanganan paket Debian. Penggunaan opsi ini wajib dalam skrip ini, sesuai kebijakan Debian; maksudnya adalah untuk menghindari kemungkinan kondisi kesalahan yang tidak tertangani.Apa artinya ini dalam praktek adalah bahwa Anda harus memahami dalam kondisi apa perintah yang Anda jalankan dapat mengembalikan kesalahan, dan menangani masing-masing kesalahan secara eksplisit.
Gotcha umum adalah eg
diff
(mengembalikan kesalahan ketika ada perbedaan) dangrep
(mengembalikan kesalahan ketika tidak ada kecocokan). Anda dapat menghindari kesalahan dengan penanganan eksplisit:(Perhatikan juga bagaimana kami berhati-hati untuk memasukkan nama skrip saat ini dalam pesan, dan menulis pesan diagnostik ke kesalahan standar alih-alih output standar.)
Jika tidak ada penanganan eksplisit yang benar-benar diperlukan atau berguna, secara eksplisit tidak melakukan apa pun:
(Penggunaan
:
perintah no-op shell sedikit tidak jelas, tetapi cukup umum terlihat.)Hanya untuk menegaskan kembali,
adalah singkatan
yaitu kami secara eksplisit mengatakan
other
harus dijalankan jika dan hanya jikasomething
gagal. Tangan lamaif
(dan pernyataan kontrol aliran shell lainnya sepertiwhile
,until
) juga merupakan cara yang valid untuk menangani kesalahan (memang, jika tidak, skrip shell denganset -e
tidak pernah dapat berisi pernyataan kontrol aliran!)Dan juga, hanya untuk menjadi eksplisit, dengan tidak adanya penangan seperti ini,
set -e
akan menyebabkan seluruh skrip segera gagal dengan kesalahan jikadiff
menemukan perbedaan, atau jikagrep
tidak menemukan kecocokan.Di sisi lain, beberapa perintah tidak menghasilkan status keluar kesalahan saat Anda menginginkannya. Perintah yang biasanya bermasalah adalah
find
(status keluar tidak mencerminkan apakah file benar-benar ditemukan) dansed
(status keluar tidak akan mengungkapkan apakah skrip menerima input atau benar-benar menjalankan perintah dengan sukses). Penjaga sederhana dalam beberapa skenario adalah menyalurkan ke perintah yang tidak menjerit jika tidak ada output:Perlu dicatat bahwa status keluar dari pipa adalah status keluar dari perintah terakhir dalam pipa itu. Jadi perintah di atas benar-benar sepenuhnya menutupi status
find
dansed
, dan hanya memberi tahu Anda apakahgrep
akhirnya berhasil.(Bash, tentu saja, memiliki
set -o pipefail
; tetapi skrip paket Debian tidak dapat menggunakan fitur Bash. Kebijakan dengan tegas menentukan penggunaan POSIXsh
untuk skrip ini, meskipun hal ini tidak selalu terjadi.)Dalam banyak situasi, ini adalah sesuatu yang harus diperhatikan secara terpisah ketika melakukan pengkodean secara defensif. Kadang-kadang Anda harus misalnya pergi melalui file sementara sehingga Anda dapat melihat apakah perintah yang menghasilkan output selesai dengan sukses, bahkan ketika idiom dan kenyamanan sebaliknya mengarahkan Anda untuk menggunakan pipa shell.
sumber
sumber