it-swarm-id.com

Exit Shell Script Berdasarkan Proses Exit Code

Saya memiliki skrip Shell yang menjalankan sejumlah perintah. Bagaimana cara saya membuat skrip Shell keluar jika ada perintah yang keluar dengan kode keluar non-nol?

364
Mark Roddy

Setelah setiap perintah, kode keluar dapat ditemukan dalam variabel $? sehingga Anda akan memiliki sesuatu seperti:

ls -al file.ext
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

Anda harus berhati-hati dengan perintah pipa karena $? hanya memberi Anda kode kembali elemen terakhir dalam pipa, jadi, dalam kode:

ls -al file.ext | sed 's/^/xx: /"

tidak akan mengembalikan kode kesalahan jika file tidak ada (karena bagian sed dari pipeline benar-benar berfungsi, mengembalikan 0).

Shell bash sebenarnya menyediakan array yang dapat membantu dalam kasus itu, yang menjadi PIPESTATUS. Array ini memiliki satu elemen untuk setiap komponen pipa, yang dapat Anda akses secara individual seperti ${PIPESTATUS[0]}:

pax> false | true ; echo ${PIPESTATUS[0]}
1

Perhatikan bahwa ini memberi Anda hasil dari perintah false, bukan seluruh pipa. Anda juga bisa mendapatkan seluruh daftar untuk diproses sesuai keinginan Anda:

pax> false | true | false; echo ${PIPESTATUS[*]}
1 0 1

Jika Anda ingin mendapatkan kode kesalahan terbesar dari sebuah pipa, Anda bisa menggunakan sesuatu seperti:

true | true | false | true | false
rcs=${PIPESTATUS[*]}; rc=0; for i in ${rcs}; do rc=$(($i > $rc ? $i : $rc)); done
echo $rc

Ini berjalan melalui masing-masing elemen PIPESTATUS pada gilirannya, menyimpannya dalam rc jika itu lebih besar dari nilai rc sebelumnya.

469
paxdiablo

Jika Anda ingin bekerja dengan $ ?, Anda harus memeriksanya setelah setiap perintah, karena $? diperbarui setelah setiap perintah keluar. Ini berarti bahwa jika Anda menjalankan pipa, Anda hanya akan mendapatkan kode keluar dari proses terakhir dalam pipa.

Pendekatan lain adalah melakukan ini:

set -e
set -o pipefail

Jika Anda meletakkan ini di bagian atas skrip Shell, sepertinya bash akan menangani ini untuk Anda. Seperti yang dicatat oleh poster sebelumnya, "set -e" akan menyebabkan bash keluar dengan kesalahan pada perintah sederhana apa pun. "set -o pipefail" akan menyebabkan bash keluar dengan kesalahan pada perintah apa pun dalam pipa juga.

Lihat di sini atau di sini untuk lebih banyak diskusi tentang masalah ini. Di Sini adalah bagian manual bash pada set builtin.

213
Jeff Hill

"set -e" mungkin cara termudah untuk melakukan ini. Masukkan saja sebelum perintah apa pun di program Anda.

50
Allen

Jika Anda hanya memanggil keluar di bash tanpa parameter, itu akan mengembalikan kode keluar dari perintah terakhir. Dikombinasikan dengan OR bash seharusnya hanya memanggil keluar, jika perintah sebelumnya gagal. Tapi saya belum menguji ini.

 command1 || keluar; 
 command2 || keluar;

Bash juga akan menyimpan kode keluar dari perintah terakhir di variabel $ ?.

28
Arvodan
[ $? -eq 0 ] || exit $?; # exit for none-zero return code
25
chemila

http://cfaj.freeshell.org/Shell/cus-faq-2.html#11

  1. Bagaimana cara mendapatkan kode keluar cmd1 di cmd1|cmd2

    Pertama, perhatikan bahwa kode keluar cmd1 bisa berupa nol dan tetap tidak berarti kesalahan. Ini terjadi misalnya di

    cmd | head -1
    

    anda mungkin mengamati 141 (atau 269 dengan ksh93) status keluar dari cmd1, tetapi itu karena cmd terganggu oleh sinyal SIGPIPE ketika head -1 diakhiri setelah membaca satu baris.

    Untuk mengetahui status keluar dari elemen-elemen pipa cmd1 | cmd2 | cmd3

    sebuah. dengan zsh:

    Kode keluar disediakan dalam larik khusus pipestatus. cmd1 kode keluar dalam $pipestatus[1], cmd3 kode keluar dalam $pipestatus[3], sehingga $? selalu sama dengan $pipestatus[-1].

    b. dengan bash:

    Kode keluar disediakan dalam larik khusus PIPESTATUS. cmd1 kode keluar dalam ${PIPESTATUS[0]}, cmd3 kode keluar dalam ${PIPESTATUS[2]}, sehingga $? selalu sama dengan ${PIPESTATUS: -1}.

    ...

    Untuk lebih jelasnya lihat berikut tautan .

21

untuk bash:

# this will trap any errors or commands with non-zero exit status
# by calling function catch_errors()
trap catch_errors ERR;

#
# ... the rest of the script goes here
#  

function catch_errors() {
   # do whatever on errors
   # 
   #
   echo "script aborted, because of errors";
   exit 0;
}
19

Dalam bash ini mudah, cukup ikat mereka dengan &&:

command1 && command2 && command3

Anda juga dapat menggunakan nested jika konstruk:

if command1
   then
       if command2
           then
               do_something
           else
               exit
       fi
   else
       exit
fi
11
Martin W
#
#------------------------------------------------------------------------------
# run a command on failure exit with message
# doPrintHelp: doRunCmdOrExit "$cmd"
# call by:
# set -e ; doRunCmdOrExit "$cmd" ; set +e
#------------------------------------------------------------------------------
doRunCmdOrExit(){
    cmd="[email protected]" ;

    doLog "DEBUG running cmd or exit: \"$cmd\""
    msg=$($cmd 2>&1)
    export exit_code=$?

    # if occured during the execution exit with error
    error_msg="Failed to run the command:
        \"$cmd\" with the output:
        \"$msg\" !!!"

    if [ $exit_code -ne 0 ] ; then
        doLog "ERROR $msg"
        doLog "FATAL $msg"
        doExit "$exit_code" "$error_msg"
    else
        #if no errors occured just log the message
        doLog "DEBUG : cmdoutput : \"$msg\""
        doLog "INFO  $msg"
    fi

}
#eof func doRunCmdOrExit
4
Yordan Georgiev