Saya sedang menulis skrip shell dan perlu memeriksa bahwa aplikasi terminal telah diinstal. Saya ingin menggunakan perintah TRY / CATCH untuk melakukan ini kecuali ada cara yang lebih rapi.
bash
shell
error-handling
Lee Probert
sumber
sumber
help test
dapat membantu Anda menemukan solusi untuk masalah Anda.trap
perintah.Jawaban:
Tidak.
Bash tidak memiliki kemewahan sebanyak yang dapat ditemukan dalam banyak bahasa pemrograman.
Tidak ada
try/catch
di bash; Namun, seseorang dapat mencapai perilaku serupa menggunakan&&
atau||
.Menggunakan
||
:jika
command1
gagal makacommand2
jalankan sebagai berikutDemikian pula, menggunakan
&&
,command2
akan berjalan jikacommand1
berhasilPerkiraan terdekat
try/catch
adalah sebagai berikutJuga bash mengandung beberapa mekanisme penanganan kesalahan, juga
itu menghentikan skrip Anda jika ada perintah sederhana gagal.
Dan juga mengapa tidak
if...else
. Itu teman baikmu.sumber
#save your output
tidak gagal, atau blok "catch" masih akan dijalankan.if...else
konstruk. Apakah ini menyiratkan bahwa perintah bash diselesaikan sebagai "benar" jika mereka berhasil dan "palsu" jika gagal?set -e
belum tentu cara terbaik untuk melakukan sesuatu; berikut adalah beberapa argumen bantahan / kasus khusus: mywiki.wooledge.org/BashFAQ/105Berdasarkan beberapa jawaban yang saya temukan di sini, saya membuat sendiri file pembantu kecil untuk sumber proyek saya:
trycatch.sh
berikut adalah contoh tampilannya saat digunakan:
sumber
||
setelahcatch
dan sebelum{}
blok? Saya akan berpikir itu adalah&&
if False or run_if_failed()
berarti bahwa korsleting ATAU mencoba pernyataan pertama yang tidak mengembalikan true dan sekarang beralih ke pernyataan berikutnya.&&
tidak akan berfungsi karena pernyataan pertama (try
) menghasilkan false, yang berarticatch
pernyataan itu tidak diperlukan oleh aturan tautologifalse&any equals false
. Hanya hubungan arus pendek AND / OR yang akan menjalankan keduanya.Saya telah mengembangkan implementasi try & catch yang hampir sempurna di bash, yang memungkinkan Anda menulis kode seperti:
Anda bahkan dapat membuat sarang blok uji coba di dalam diri mereka!
Kode ini adalah bagian dari bash boilerplate / framework saya . Lebih lanjut memperluas gagasan mencoba & menangkap dengan hal-hal seperti penanganan kesalahan dengan backtrace dan pengecualian (ditambah beberapa fitur bagus lainnya).
Berikut kode yang bertanggung jawab hanya untuk mencoba & menangkap:
Jangan ragu untuk menggunakan, garpu, dan berkontribusi - ini ada di GitHub .
sumber
my_output=$(try { code...; } catch { code...; })
Anda bisa menggunakan
trap
:try { block A } catch { block B } finally { block C }
diterjemahkan menjadi:
sumber
-E
bendera yang saya pikir, sehingga jebakan menyebar ke fungsiAda begitu banyak solusi serupa yang mungkin berhasil. Di bawah ini adalah cara sederhana dan bekerja untuk mencapai try / catch, dengan penjelasan di komentar.
sumber
bash
tidak membatalkan eksekusi yang berjalan jika ada sesuatu yang mendeteksi keadaan kesalahan (kecuali jika Anda mengatur-e
bendera). Memprogram bahasa yang menawarkantry/catch
melakukan ini untuk menghambat "bailing out" karena situasi khusus ini (karenanya biasanya disebut "pengecualian").Dalam
bash
, sebaliknya, hanya perintah tersebut akan keluar dengan kode yang lebih besar keluar dari 0, menunjukkan bahwa kesalahan negara. Anda dapat memeriksa itu tentu saja, tetapi karena tidak ada bailing otomatis dari apa pun, mencoba / menangkap tidak masuk akal. Itu hanya kurang konteks itu.Anda dapat, bagaimanapun, mensimulasikan bailing out dengan menggunakan sub shell yang dapat berakhir pada saat Anda memutuskan:
Alih-alih
some_condition
denganif
Anda juga bisa mencoba perintah, dan jika gagal (memiliki kode keluar lebih besar dari 0), bail out:Sayangnya, menggunakan teknik ini Anda dibatasi pada 255 kode keluar yang berbeda (1..255) dan tidak ada objek pengecualian yang dapat digunakan.
Jika Anda membutuhkan lebih banyak informasi untuk menyampaikan pengecualian simulasi Anda, Anda dapat menggunakan stdout subshell, tetapi itu sedikit rumit dan mungkin pertanyaan lain ;-)
Menggunakan
-e
flag yang disebutkan di atas untuk shell Anda bahkan dapat menghapusexit
pernyataan eksplisit itu :sumber
Seperti yang dikatakan semua orang, bash tidak memiliki sintaks coba / tangkap bahasa yang didukung dengan tepat. Anda dapat meluncurkan bash dengan
-e
argumen atau gunakanset -e
di dalam skrip untuk membatalkan seluruh proses bash jika ada perintah yang memiliki kode keluar nol. (Anda juga bisaset +e
dapat mengizinkan sementara perintah yang gagal.)Jadi, satu teknik untuk mensimulasikan blok coba / tangkap adalah meluncurkan sub-proses untuk melakukan pekerjaannya
-e
diaktifkan. Kemudian dalam proses utama, periksa kode pengembalian sub-proses.Bash mendukung string heredoc, jadi Anda tidak perlu menulis dua file terpisah untuk menangani ini. Pada contoh di bawah ini, heredoc TRY akan berjalan dalam instance bash terpisah, dengan
-e
diaktifkan, sehingga sub-proses akan macet jika ada perintah yang mengembalikan kode keluar yang tidak nol. Kemudian, kembali ke proses utama, kita dapat memeriksa kode kembali untuk menangani catch block.Ini bukan blok coba / tangkap yang didukung bahasa yang tepat, tetapi mungkin menggaruk gatal yang serupa untuk Anda.
sumber
Anda dapat melakukan:
sumber
Dan Anda memiliki perangkap http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html yang tidak sama, tetapi teknik lain yang dapat Anda gunakan untuk tujuan ini
sumber
Suatu hal yang sangat sederhana yang saya gunakan:
sumber
||
berada di()
, itu akan berjalan dalam subkulit dan keluar, tanpa menyebabkan shell utama keluar. Gunakan{ }
pengelompokan sebagai gantinya.Di bawah ini adalah salinan lengkap dari skrip sederhana yang digunakan dalam jawaban saya yang lain . Selain pemeriksaan kesalahan tambahan, ada alias yang memungkinkan pengguna untuk mengubah nama alias yang ada. Sintaks diberikan di bawah ini. Jika
new_alias
parameter dihilangkan, maka alias dihapus.Script lengkap diberikan di bawah ini.
sumber
Di bawah ini adalah contoh skrip yang mengimplementasikan
try/catch/finally
bash.Contoh skrip dimulai dengan membuat anonim fifo, yang digunakan untuk meneruskan pesan string dari
command exception
atauthrow
ke akhirtry
blok terdekat . Di sini pesan dihapus dari fifo dan ditempatkan dalam variabel array. Status dikembalikan melaluireturn
danexit
perintah dan ditempatkan di variabel yang berbeda. Untuk memasukkancatch
blok, status ini tidak boleh nol. Persyaratan lain untuk memasukkancatch
blok dilewatkan sebagai parameter. Jika akhir acatch
blok tercapai, maka status diatur ke nol. Jika akhirfinally
blok tercapai dan statusnya masih nol, maka lemparan implisit yang berisi pesan dan status dieksekusi. Script membutuhkan pemanggilan fungsitrycatchfinally
yang berisi penangan pengecualian yang tidak tertangani.Sintaks untuk
trycatchfinally
perintah diberikan di bawah ini.The
-c
pilihan menambahkan tumpukan panggilan ke pesan pengecualian.The
-d
pilihan memungkinkan debug output.The
-e
pilihan memungkinkan pengecualian perintah.The
-h
pilihan memungkinkan pengguna untuk mengganti sendiri handler perintah pengecualian mereka.The
-k
pilihan menambahkan panggilan stack ke output debug.The
-o
pilihan menggantikan file output standar yang/dev/fd/2
.The
-u
pilihan memungkinkan pengguna untuk mengganti tertangani handler pengecualian mereka sendiri.The
-v
pilihan memungkinkan pengguna pilihan untuk lulus kembali nilai-nilai meskipun penggunaan Command Pergantian.The
fifo
adalah FIFO nama file.Fungsi
function
ini disebuttrycatchfinally
sebagai subproses.Sintaks untuk
catch
perintah diberikan di bawah ini.Opsi ditentukan di bawah ini. Nilai untuk daftar pertama adalah status. Nilai subsquent adalah pesannya. Jika ada lebih banyak pesan daripada daftar, maka pesan yang tersisa diabaikan.
-e
berarti[[ $value == "$string" ]]
(nilai harus cocok dengan setidaknya satu string dalam daftar)-n
berarti[[ $value != "$string" ]]
(nilai tidak dapat cocok dengan string apa pun dalam daftar)-o
berarti[[ $value != $pattern ]]
(nilai tidak dapat cocok dengan salah satu pola dalam daftar)-p
berarti[[ $value == $pattern ]]
(nilai memiliki untuk mencocokkan setidaknya satu pola dalam daftar)-r
berarti[[ $value =~ $regex ]]
(nilai harus cocok dengan setidaknya satu ekspresi reguler yang diperluas dalam daftar)-t
berarti[[ ! $value =~ $regex ]]
(nilai tidak dapat cocok dengan salah satu dari ekspresi reguler yang diperluas dalam daftar)The
try/catch/finally
Script diberikan di bawah ini. Untuk menyederhanakan skrip untuk jawaban ini, sebagian besar pengecekan kesalahan dihapus. Ini mengurangi ukuran sebesar 64%. Salinan lengkap skrip ini dapat ditemukan di jawaban saya yang lain .Di bawah ini adalah contoh, yang mengasumsikan skrip di atas disimpan dalam file bernama
simple
. Themakefifo
file berisi script yang dijelaskan dalam jawaban ini . Asumsi dibuat bahwa file bernama4444kkkkk
tidak ada, oleh karena itu menyebabkan pengecualian terjadi. Output pesan kesalahan darils 4444kkkkk
perintah secara otomatis ditekan hingga di dalamcatch
blok yang sesuai .Script di atas diuji menggunakan
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. Output, dari menjalankan skrip ini, ditampilkan di bawah ini.Contoh lain yang menggunakan a
throw
dapat dibuat dengan mengganti fungsiMyFunction3
dengan skrip yang ditunjukkan di bawah ini.Sintaks untuk
throw
perintah diberikan di bawah ini. Jika tidak ada parameter, maka status dan pesan yang disimpan dalam variabel digunakan sebagai gantinya.Output, dari menjalankan skrip yang dimodifikasi, ditampilkan di bawah ini.
sumber