Bagaimana cara memeriksa apakah suatu perintah berhasil?

235

Apakah ada cara untuk memeriksa apakah ada kesalahan dalam menjalankan perintah?

Contoh:

test1=`sed -i "/:@/c connection.url=jdbc:oracle:thin:@$ip:1521:$dataBase" $search`
valid $test1

function valid () {
  if $test -eq 1; then
    echo "OK"
    else echo "ERROR" 
  fi
}

Saya sudah mencoba melakukan itu tetapi tampaknya itu tidak berhasil. Saya tidak tahu bagaimana melakukannya.

moata_u
sumber
9
Lebih suka $ (foo) daripada backticks `foo` , karena Anda dapat membuat sarangnya, dan lebih mudah untuk membedakan dari apostrof.
pengguna tidak dikenal
1
BTW, Anda perlu mendefinisikan suatu fungsi ( valid) sebelum Anda menyebutnya.
wjandrea

Jawaban:

345

Nilai pengembalian disimpan di $?. 0 menunjukkan keberhasilan, yang lain menunjukkan kesalahan.

some_command
if [ $? -eq 0 ]; then
    echo OK
else
    echo FAIL
fi

Seperti nilai tekstual lainnya, Anda dapat menyimpannya dalam variabel untuk perbandingan di masa mendatang:

some_command
retval=$?
do_something $retval
if [ $retval -ne 0 ]; then
    echo "Return code was not zero but $retval"
fi

Untuk kemungkinan operator perbandingan, lihat man test.

Lekensteyn
sumber
Itu bagus ... bisakah saya menahan kesalahan output ?? !! , karena dalam kasus ini saya memiliki 2 kesalahan: kesalahan perintah "teks" ex, file tidak ditemukan dan kesalahan "teks" saya yang dalam hal ini gagal misalnya
moata_u
@moata_u: Anda dapat menyimpan nilai dalam variabel seperti yang ditunjukkan dalam jawaban saya.
Lekensteyn
@moata_u: Anda harus meletakkan ;sebelum elsedan fi: `jika ...; kemudian ...; lain ...; fi
Lekensteyn
4
Ini adalah penggunaan yang tidak bergunatest .
David Foerster
1
@Blauhirn [ $? ](atau yang setara, test $?) tidak berfungsi karena $?dievaluasi ke nomor (0, 1, dll.) Yang bukan nol. Lihat dokumen untuktest : "Jika EXPRESSION dihilangkan, 'test' mengembalikan false. Jika EXPRESSION adalah argumen tunggal, 'test' mengembalikan false jika argumen tersebut null dan benar sebaliknya."
Lekensteyn
87

Jika Anda hanya perlu tahu apakah perintah itu berhasil atau gagal, jangan repot-repot menguji $?, cukup uji perintah secara langsung. Misalnya:

if some_command; then
    printf 'some_command succeeded\n'
else
    printf 'some_command failed\n'
fi

Dan menugaskan output ke variabel tidak mengubah nilai kembali (well, kecuali jika berperilaku berbeda ketika stdout bukan terminal tentu saja).

if output=$(some_command); then
    printf 'some_command succeded, the output was «%s»\n' "$output"
fi

http://mywiki.wooledge.org/BashGuide/TestsAndConditionals menjelaskan iflebih detail.

geirha
sumber
Bagaimana jika Anda ingin melakukan sesuatu selain percabangan seperti menyimpan boolean apakah gagal atau tidak ke dalam .ini? Maka variabel output Anda tidak melakukan itu, tetapi $?melakukannya, jadi Anda salah mengatakan bahwa menguji perintah secara langsung lebih baik.
Timothy Swan
Menetapkan output ke variabel dapat mengubah nilai kembali ketika seseorang menggunakan localperintah, yaitu local foo=$(false); echo $?;menghasilkan 0pada output. Tetapi localhanya relevan di dalam fungsi bash.
Cromax
26
command && echo OK || echo Failed
Abraham Sanchez
sumber
Jika commandmengembalikan kesalahan di layar, bagaimana cara menyembunyikannya?
Sigur
Jika commandmenulis kesalahan ke stderr, Anda dapat menggunakan formulir command 2> /dev/null && echo OK || echo Failed. The 2> /dev/nullpengalihan stderr output ke /dev/null. Namun, beberapa utilitas akan menulis kesalahan ke stdout (meskipun ini adalah praktik buruk). Dalam hal ini Anda dapat menghilangkan 2 dari pengalihan, tetapi Anda akan kehilangan output dari perintah. Metode memeriksa keberhasilan ini baik untuk logika terner sederhana tetapi untuk perilaku yang lebih kompleks, yang terbaik adalah memeriksa $?keberhasilan perintah, atau menggunakan ifmetode blok yang diuraikan dalam jawaban @ geirha.
Bender the Greatest
17

$? harus berisi status keluar dari perintah sebelumnya, yang seharusnya nol tanpa kesalahan.

Jadi, sesuatu seperti;

cd /nonexistant
if [ $? -ne 0 ]
then
    echo failed
else
    echo success!
fi

untuk sebagian besar kasus, lebih mudah menggunakan && membangun untuk mengaitkan perintah yang harus saling bergantung. Jadi tidakcd /nonexistant && echo success! akan menggemakan kesuksesan karena perintahnya rusak sebelum &&. Konsekuensi dari ini adalah ||, di mana gema akan gagal karena cd gagal. (ini menjadi berguna jika Anda menggunakan sesuatu seperti || keluar, yang akan mengakhiri skrip jika perintah sebelumnya gagal.)cd /nonexistant || echo fail

Shaun
sumber
Itu bagus ... bisakah saya menahan kesalahan output ?? !! , karena dalam kasus ini saya memiliki 2 kesalahan: kesalahan perintah "teks" ex, file tidak ditemukan dan kesalahan "teks" saya yang dalam hal ini gagal misalnya
moata_u
@moata_u, lihat mywiki.wooledge.org/BashFAQ/002
geirha
5
command && echo $? || echo $?
modrobert
sumber
Maksudmu command; echo $??
Javier Buzzi
Tidak, baris saya benar, ia memberikan kode hasil aktual sebagai nomor terlepas dari apakah berhasil atau gagal.
modrobert
1
Ok, tolong jelaskan perbedaannya kepada saya: true && echo $? || echo $?/ true; echo $?dan false && echo $? || echo $?/ false; echo $?- Anda akan menemukan, mereka melakukan hal yang sama persis: D
Javier Buzzi
Ya, hasilnya sama tetapi tanpa syarat. Pertanyaan awal yang diajukan adalah "Bagaimana cara memeriksa apakah suatu perintah berhasil?", Ini didasarkan pada jawaban sebelumnya. Saya kira contoh yang lebih baik adalah:command && echo "success: $?" || echo "fail: $?"
modrobert
5

Perlu dicatat bahwa if...then...fidan &&/ ||jenis pendekatan berkaitan dengan status keluar yang dikembalikan oleh perintah yang ingin kami uji (0 saat berhasil); namun, beberapa perintah tidak mengembalikan status keluar yang tidak nol jika perintah gagal atau tidak dapat menangani input. Ini berarti bahwa pendekatan biasa ifdan &&/ ||tidak akan bekerja untuk perintah-perintah tertentu.

Misalnya, di Linux, GNU filemasih keluar dengan 0 jika menerima file yang tidak ada sebagai argumen dan findtidak dapat menemukan file yang ditentukan pengguna.

$ find . -name "not_existing_file"                                          
$ echo $?
0
$ file ./not_existing_file                                                  
./not_existing_file: cannot open `./not_existing_file' (No such file or directory)
$ echo $?
0

Dalam kasus seperti itu, salah satu cara potensial kita dapat menangani situasi adalah dengan membaca stderr/ stdinpesan, misalnya yang dikembalikan dengan fileperintah, atau parse output dari perintah seperti di find. Untuk tujuan itu, casepernyataan dapat digunakan.

$ file ./doesntexist  | while IFS= read -r output; do                                                                                                                  
> case "$output" in 
> *"No such file or directory"*) printf "%s\n" "This will show up if failed";;
> *) printf "%s\n" "This will show up if succeeded" ;;
> esac
> done
This will show up if failed

$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi                                                                                     
File not found

(Ini adalah repost jawaban saya sendiri pada pertanyaan terkait di unix.stackexchange.com )

Sergiy Kolodyazhnyy
sumber
1

Seperti disebutkan dalam banyak jawaban lain, tes sederhana $?akan dilakukan, seperti ini

if [ $? -eq 0 ]; then something; fi

Jika Anda ingin menguji apakah perintah gagal , Anda dapat menggunakan versi yang lebih pendek di bash(tapi mungkin berlebihan) sebagai berikut:

if (($?)); then something; fi

Ini bekerja dengan menggunakan (( ))mode aritmatika, jadi jika perintah kembali success, yaitu $? = 0tes mengevaluasi untuk ((0))tes mana false, jika tidak maka akan kembali true.

Untuk menguji kesuksesan , Anda dapat menggunakan:

if ! (($?)); then something; fi

tapi itu sudah tidak jauh lebih pendek dari contoh pertama.

afuna
sumber
1
kritik membangun?
afuna