Keluar dari Script On Error


146

Saya sedang membangun Shell Script yang memiliki iffungsi seperti ini:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables
fi

...

Saya ingin eksekusi skrip selesai setelah menampilkan pesan kesalahan. Bagaimana saya bisa melakukan ini?

Jawaban:


142

Apakah kamu sedang mencari exit?

Ini adalah panduan pesta terbaik. http://tldp.org/LDP/abs/html/

Dalam konteks:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables 1>&2
    exit 1 # terminate and indicate error
fi

...

5
Jika Anda menyukai ABS, Anda akan menyukai BashGuide , BashFAQ dan BashPitfalls .
Dijeda sampai pemberitahuan lebih lanjut.

Tautan Bash itu LUAR BIASA! BashFAQ akan lebih baik ditempatkan sebagai BashRecipes.
Pete Alvin

343

Jika Anda memasukkan set -eskrip, skrip akan berhenti segera setelah perintah di dalamnya gagal (yaitu segera setelah perintah mengembalikan status bukan nol). Ini tidak memungkinkan Anda menulis pesan Anda sendiri, tetapi seringkali pesan perintah yang gagal itu sendiri sudah cukup.

Keuntungan dari pendekatan ini adalah sifatnya otomatis: Anda tidak mengambil risiko lupa menangani kasus kesalahan.

Perintah yang statusnya diuji dengan kondisional (seperti if, &&atau ||) tidak menghentikan skrip (jika tidak, kondisional tidak ada gunanya). Sebuah idiom untuk perintah sesekali yang kegagalannya tidak penting command-that-may-fail || true. Anda juga dapat set -emematikan sebagian skrip dengan set +e.


3
Menurut mywiki.wooledge.org/BashFAQ/105 - fitur ini memiliki riwayat tidak jelas dan berbelit-belit dalam menentukan kode kesalahan perintah mana yang menyebabkan keluar otomatis. Lebih lanjut, "aturan berubah dari satu versi Bash ke versi lainnya, karena Bash mencoba melacak definisi POSIX yang sangat licin dari 'fitur' ini". Saya setuju dengan @Dennis Williamson dan jawaban yang diterima dari stackoverflow.com/questions/19622198/… - gunakan perangkap 'error_handler' ERR. Bahkan jika itu jebakan!
Bondolin

3
sering menggunakan -xflag dengan -eflag sudah cukup untuk melacak di mana program Anda saat keluar. Itu menyiratkan bahwa pengguna skrip juga merupakan pengembang.
Alexander Oh

Bagus tapi saya pikir OP perlu keluar dari skrip dari pengecualian yang ditentukan sendiri.
vdegenne

44

Jika Anda ingin menangani kesalahan alih-alih keluar secara membabi buta, alih-alih menggunakan set -e, gunakan a trappada ERRsinyal pseudo.

#!/bin/bash
f () {
    errorCode=$? # save the exit code as the first thing done in the trap function
    echo "error $errorCode"
    echo "the command executing at the time of the error was"
    echo "$BASH_COMMAND"
    echo "on line ${BASH_LINENO[0]}"
    # do some error handling, cleanup, logging, notification
    # $BASH_COMMAND contains the command that was being executed at the time of the trap
    # ${BASH_LINENO[0]} contains the line number in the script of that command
    # exit the script or return to try again, etc.
    exit $errorCode  # or use some other value or do return instead
}
trap f ERR
# do some stuff
false # returns 1 so it triggers the trap
# maybe do some other stuff

Perangkap lain dapat diatur untuk menangani sinyal lain, termasuk sinyal Unix biasa ditambah sinyal pseudo Bash lainnya RETURNdan DEBUG.


9

Inilah cara melakukannya:

#!/bin/sh

abort()
{
    echo >&2 '
***************
*** ABORTED ***
***************
'
    echo "An error occurred. Exiting..." >&2
    exit 1
}

trap 'abort' 0

set -e

# Add your script below....
# If an error occurs, the abort() function will be called.
#----------------------------------------------------------
# ===> Your script goes here
# Done!
trap : 0

echo >&2 '
************
*** DONE *** 
************
'

Mengapa pesan SELESAI ke stderr?
MattBianco

1
Ini adalah praktik umum sehingga Anda dapat menyalurkan output skrip Anda ke stdout sehingga proses lain bisa mendapatkannya tanpa pesan info di tengah.
supercobra

2
Mungkin merupakan praktik yang sama umum untuk memperlakukan apa pun di stderr sebagai indikasi masalah.
MattBianco

1
Di masa lalu, 'set -e' selalu berhasil untuk saya, tetapi malam ini saya menemukan situasi dalam image Docker Linux Alpine di mana itu tidak berpengaruh .. Solusi ini bekerja untuk saya dan membuat saya kembali pada tugas yang ada. Sangat dihargai.
synthesizerpatel

@supercobra Praktek umum? Dimana?
Thorbjørn Ravn Andersen

-8

exit 1adalah semua yang Anda butuhkan. Ini 1adalah kode pengembalian, sehingga Anda dapat mengubahnya jika Anda ingin, katakanlah, 1berarti proses yang sukses dan -1berarti kegagalan atau semacamnya.


14
Dalam unix, kesuksesan selalu 0. Ini mungkin membantu saat menggunakan testatau &&atau ||.
mouviciel

5
Untuk memperluas komentar mouviciel: dalam skrip shell, 0 selalu berarti sukses, dan 1 hingga 255 berarti kegagalan. -1 di luar jangkauan (dan akan sering memiliki efek yang sama seperti 255, jadi kegagalan seperti 1).
Gilles 'SO- berhenti bersikap jahat'

@mouviciel, @Gilles: Terima kasih atas info tambahannya. Sudah lama sejak saya berurusan dengan pesta.
DJBM

Ini adalah contoh buruk penggunaan kode pengembalian, jika tidak maka akan menjadi jawaban yang bagus.
Brad Koch

1
Selain salah merekomendasikan 1 untuk sukses, -1 tidak mungkin (kode keluar tidak bertanda tangan).
tripleee
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.