Saya memiliki skrip bash yang digunakan set -o errexit
sehingga saat kesalahan seluruh skrip keluar pada titik kegagalan.
Skrip menjalankan curl
perintah yang terkadang gagal untuk mengambil file yang dimaksud - namun ketika ini terjadi skrip tidak keluar.
Saya telah menambahkan satu for
loop ke
- jeda selama beberapa detik kemudian coba lagi
curl
perintah - gunakan
false
di bagian bawah for loop untuk menentukan status keluar non-nol default - jika perintah curl berhasil - loop rusak dan status keluar dari perintah terakhir harus nol.
#! /bin/bash
set -o errexit
# ...
for (( i=1; i<5; i++ ))
do
echo "attempt number: "$i
curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
if [ -f ~/.vim/autoload/pathogen.vim ]
then
echo "file has been retrieved by curl, so breaking now..."
break;
fi
echo "curl'ed file doesn't yet exist, so now will wait 5 seconds and retry"
sleep 5
# exit with non-zero status so main script will errexit
false
done
# rest of script .....
Masalahnya adalah ketika curl
perintah gagal, loop mengulangi perintah lima kali - jika semua upaya tidak berhasil maka for loop selesai dan script utama dilanjutkan - alih-alih memicu errexit
.
Bagaimana saya bisa membuat seluruh skrip keluar jika curl
pernyataan ini gagal?
sumber
true
sebelum pernyataan break menjadi eksplisit dan memastikan nilai keluar dari loop?exit 1
ketika sekadarexit
akan berhasil. Namun, ini adalah masalah gaya dan orang lain dapat memiliki pendapat mereka sendiri.exit
sebagai pintu keluar sederhana - yang mengakhiri skrip dengan sendirinya.exit 1
akan membacakan kepada saya sebagai "sinyal" untuk beberapa proses lain (yaituerrexit
) - bahwa itu harus mengakhiri skrip berdasarkan "hasil" dariexit 1
. - jadi saya telah pergi denganexit
tetapi terima kasih untuk penjelasannyaexit 1
. Itu tidak mempengaruhierrexit
sama sekali. Itu hanya memberitahu program panggilan bahwa ada yang tidak beres. Thefalse
perintah berisi satu pernyataan:exit(1)
. 99,9% dari perintah Unix mengembalikan 0 pada keberhasilan dan bukan nol pada kesalahan. Anda juga harus.Jika Anda telah
errexit
mengatur, makafalse
pernyataan tersebut akan menyebabkan skrip segera keluar. Hal yang sama jikacurl
perintah gagal.Contoh skrip Anda, seperti yang ditulis, harus keluar setelah
curl
kegagalan perintah pertama saat panggilan pertama kalifalse
jika errexit diatur.Untuk melihat cara kerjanya (saya menggunakan singkatan
-e
untuk mengaturerrexit
:Jadi, jika
curl
perintah dijalankan lebih dari sekali, skrip ini tidakerrexit
disetel.sumber
set -e
lebih halus dari itu. Itu tidak akan keluar setelah perintah pertama gagal dalam satu lingkaran. Anda dapat membuktikannya sendiri dengan menjalankan(set -e; for (( i=1; i<5; i++ )); do echo $i; false; done || echo "FAIL"; )
dan mencatat bahwa kode tersebut berjalanfalse
empat kali. Untuk informasi lebih lanjutset -e
, lihat FAQ Greg # 105 .errexit
belum ditetapkan. Silakan terapkan logika pada skrip dalam pertanyaan. Jalankan ini:(set -e; for (( i=1; i<5; i++ )); do echo $i; false; done ; echo still here )
Ya menguji nilai kembali denganif
while
||
&&
dll tidak memicu errexit. Script asli bukan||
untuk loop.set -o errexit
perintah dalam kode contoh saya, telah menambahkannya sekarang - dan bagi saya itu bukan kesalahan yang keluar seperti yang diharapkan. Saya perlu menjagafalse
sebagai perintah terakhir dalam for loop, kemudian tutup dengandone || exit [1]
- maka itu bekerja dengan baik!set -o errexit
dapat menjadi rumit dalam loop dan subkulit, karena Anda harus melewati jalan keluar dari proses.Memutuskan loop (bahkan dalam operasi normal) dianggap praktik yang buruk. Anda dapat memanggil saya old-school untuk memilih while-loop daripada for-loop untuk dua kondisi, tetapi saya merasa lebih baik membaca:
sumber
Jika
errexit
diatur dancurl
perintah gagal, skrip berakhir tepat setelah perintah keriting yang gagal. Dalam manual bash, tidak ada petunjuk yangset -e
mengabaikan status pengembalian tunggal yang gagal pada perintah majemuk. Ini hanya akan menjadi kasus jika perintah gabungan dieksekusi dalam konteks di manaset -e
diabaikan.https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin
Coba contoh yang sedikit diadaptasi yang diposting oleh RobertL. Ini berhenti pada iterasi pertama tepat setelah perintah salah:
sumber
Anda cukup menambahkan opsi --fail ke perintah curl, ini akan menyelesaikan masalah Anda, skrip akan gagal dan keluar dari kesalahan jika perintah curl gagal, jika sangat berguna juga saat menggunakan curl di jenkins pipeline:
sumber