Cara Menjebak Kesalahan dalam Skrip Bash di Linux

Diterbitkan: 2022-08-27
Laptop Linux menampilkan prompt bash
fatmawati achmad zaenuri/Shutterstock.com

Secara default, skrip Bash di Linux akan melaporkan kesalahan tetapi tetap berjalan. Kami menunjukkan kepada Anda bagaimana menangani kesalahan sendiri sehingga Anda dapat memutuskan apa yang perlu terjadi selanjutnya.

Penanganan Kesalahan dalam Skrip

Menangani kesalahan adalah bagian dari pemrograman. Bahkan jika Anda menulis kode tanpa cacat, Anda masih dapat mengalami kondisi kesalahan. Lingkungan di komputer Anda berubah seiring waktu, saat Anda menginstal dan menghapus instalan perangkat lunak, membuat direktori, dan melakukan peningkatan dan pembaruan.

Menyesuaikan Kesalahan Validasi Parameter Di PowerShell
Kesalahan Validasi Parameter Penyesuaian TERKAIT Di PowerShell

Misalnya, skrip yang digunakan untuk berjalan tanpa masalah dapat mengalami kesulitan jika jalur direktori berubah, atau izin diubah pada file. Tindakan default shell Bash adalah mencetak pesan kesalahan dan terus menjalankan skrip. Ini adalah default yang berbahaya.

Jika tindakan yang gagal sangat penting untuk beberapa pemrosesan atau tindakan lain yang terjadi kemudian di skrip Anda, tindakan kritis itu tidak akan berhasil. Betapa berbahayanya itu, tergantung pada apa yang coba dilakukan skrip Anda.

Skema yang lebih kuat akan mendeteksi kesalahan dan membiarkan skrip bekerja jika perlu dimatikan atau mencoba memperbaiki kondisi kesalahan. Misalnya, jika direktori atau file tidak ada, mungkin cukup memuaskan jika skrip dibuat ulang.

Jika skrip mengalami masalah yang tidak dapat dipulihkan, skrip dapat dimatikan. Jika skrip harus dimatikan, skrip dapat memiliki kesempatan untuk melakukan pembersihan apa pun yang diperlukan, seperti menghapus file sementara atau menulis kondisi kesalahan dan alasan penonaktifan ke file log.

Mendeteksi Status Keluar

Perintah dan program menghasilkan nilai yang dikirim ke sistem operasi saat dihentikan. Ini disebut status keluar mereka. Ini memiliki nilai nol jika tidak ada kesalahan, atau nilai bukan nol jika terjadi kesalahan.

Kita dapat memeriksa status keluar—juga dikenal sebagai kode kembali—dari perintah yang digunakan skrip, dan menentukan apakah perintah itu berhasil atau tidak.

Di Bash, nol sama dengan benar. Jika respons dari perintah tidak benar, kami tahu ada masalah yang terjadi dan kami dapat mengambil tindakan yang tepat.

Salin skrip ini ke editor, dan simpan ke file bernama “bad_command.sh.”

 #!/bin/bash

jika ( ! bad_command ); kemudian
  echo "bad_command menandai kesalahan."
  keluar 1
fi

Anda harus membuat skrip dapat dieksekusi dengan perintah chmod . Ini adalah langkah yang diperlukan untuk membuat skrip apa pun dapat dieksekusi, jadi jika Anda ingin mencoba skrip di mesin Anda sendiri, ingatlah untuk melakukan ini untuk masing-masing skrip. Ganti nama skrip yang sesuai dalam setiap kasus.

 chmod +x bad_command.sh 

Membuat skrip dapat dieksekusi dengan menggunakan chmod

Saat kami menjalankan skrip, kami melihat pesan kesalahan yang diharapkan.

 ./bad_command.sh 

Memeriksa status keluar dari suatu perintah untuk menentukan apakah telah terjadi kesalahan

Tidak ada perintah seperti "bad_command", juga bukan nama fungsi di dalam skrip. Itu tidak dapat dieksekusi, jadi responsnya tidak nol. Jika responsnya bukan nol—tanda seru digunakan di sini sebagai operator NOT logis—tubuh pernyataan if dieksekusi.

Dalam skrip dunia nyata, ini dapat menghentikan skrip, yang dilakukan oleh contoh kita, atau dapat mencoba memperbaiki kondisi kesalahan.

Mungkin terlihat seperti jalur exit 1 berlebihan. Lagi pula, tidak ada yang lain dalam skrip dan itu akan tetap berakhir. Tetapi menggunakan perintah exit memungkinkan kita untuk meneruskan status keluar kembali ke shell. Jika skrip kita dipanggil dari dalam skrip kedua, skrip kedua itu akan mengetahui bahwa skrip ini mengalami kesalahan.

Anda dapat menggunakan operator logika OR dengan status keluar dari suatu perintah, dan memanggil perintah atau fungsi lain dalam skrip Anda jika ada respons bukan nol dari perintah pertama.

 perintah_1 || perintah_2

Ini berfungsi karena perintah pertama berjalan OR yang kedua. Perintah paling kiri dijalankan terlebih dahulu. Jika berhasil perintah kedua tidak dijalankan. Tetapi jika perintah pertama gagal, perintah kedua dijalankan. Jadi kita bisa menyusun kode seperti ini. Ini adalah "logis-or./sh."

 #!/bin/bash

kesalahan_penangan()
{
  echo "Kesalahan: ($?) $1"
  keluar 1
}

perintah_buruk || error_handler "bad_command gagal, Baris: ${LINENO}"

Kami telah mendefinisikan fungsi yang disebut error_handler . Ini mencetak status keluar dari perintah yang gagal, disimpan dalam variabel $? dan sebaris teks yang diteruskan ke sana saat fungsi dipanggil. Ini disimpan dalam variabel $1 . Fungsi mengakhiri skrip dengan status keluar satu.

Script mencoba menjalankan bad_command yang jelas-jelas gagal, jadi perintah di sebelah kanan operator logika OR , || , dieksekusi. Ini memanggil fungsi error_handler dan meneruskan string yang menamai perintah yang gagal, dan berisi nomor baris dari perintah yang gagal.

Kami akan menjalankan skrip untuk melihat pesan penangan kesalahan, dan kemudian memeriksa status keluar skrip menggunakan echo.

 ./logis-or.sh
 gema $? 

Menggunakan operator OR logis untuk memanggil penangan kesalahan dalam skrip

Fungsi error_handler kecil kami menyediakan status keluar dari upaya menjalankan bad_command , nama perintah, dan nomor baris. Ini adalah informasi yang berguna saat Anda men-debug skrip.

Status keluar dari skrip adalah satu. Status keluar 127 yang dilaporkan oleh error_handler berarti "perintah tidak ditemukan." Jika kita mau, kita bisa menggunakannya sebagai status keluar dari skrip dengan meneruskannya ke perintah exit .

Pendekatan lain adalah memperluas error_handler untuk memeriksa kemungkinan nilai yang berbeda dari status keluar dan untuk melakukan tindakan yang berbeda sesuai dengan itu, menggunakan jenis konstruksi ini:

 kode_keluar=$?

if [ $exit_code -eq 1 ]; kemudian
  echo "Operasi tidak diizinkan"

elif [ $exit_code -eq 2 ]; kemudian
  echo "Penyalahgunaan shell bawaan"
.
.
.
elif [ $status -eq 128 ]; kemudian
  echo "Argumen tidak valid"
fi

Menggunakan set Untuk Memaksa Keluar

Jika Anda tahu bahwa Anda ingin skrip Anda keluar setiap kali ada kesalahan, Anda dapat memaksanya untuk melakukannya. itu berarti Anda mengabaikan kemungkinan pembersihan—atau kerusakan lebih lanjut, juga—karena skrip Anda berhenti segera setelah mendeteksi kesalahan.

Untuk melakukan ini, gunakan perintah set dengan opsi -e (error). Ini memberitahu skrip untuk keluar setiap kali perintah gagal atau mengembalikan kode keluar lebih besar dari nol. Juga, menggunakan opsi -E memastikan deteksi kesalahan dan perangkap berfungsi dalam fungsi shell.

Cara Menggunakan set dan pipefail di Bash Script di Linux
TERKAIT Cara Menggunakan set dan pipefail di Bash Script di Linux

Untuk juga menangkap variabel yang tidak diinisialisasi, tambahkan opsi -u (tidak disetel). Untuk memastikan bahwa kesalahan terdeteksi dalam urutan pipa, tambahkan opsi -o pipefail . Tanpa ini, status keluar dari urutan perintah yang disalurkan adalah status keluar dari perintah terakhir dalam urutan. Perintah yang gagal di tengah urutan pipa tidak akan terdeteksi. Opsi -o pipefail harus ada dalam daftar opsi.

Urutan untuk ditambahkan ke bagian atas skrip Anda adalah:

 set -Eeuo pipefail

Berikut adalah skrip pendek yang disebut "unset-var.sh", dengan variabel yang tidak disetel di dalamnya.

 #!/bin/bash

set -Eeou pipefail

echo "$variabel_tidak disetel"

echo "Apakah kita melihat baris ini?"

Ketika kami menjalankan skrip, unset_variable dikenali sebagai variabel yang tidak diinisialisasi dan skrip dihentikan.

 ./unset-var.sh 

Menggunakan perintah set dalam skrip untuk menghentikan skrip jika terjadi kesalahan

Perintah echo kedua tidak pernah dieksekusi.

Menggunakan perangkap Dengan Kesalahan

Perintah Bash trap memungkinkan Anda menominasikan perintah atau fungsi yang harus dipanggil saat sinyal tertentu dinaikkan. Biasanya ini digunakan untuk menangkap sinyal seperti SIGINT yang muncul saat Anda menekan kombinasi tombol Ctrl+C. Skrip ini adalah "sigint.sh."

 #!/bin/bash

trap "echo -e '\nDihentikan oleh Ctrl+c'; keluar" TANDA

penghitung = 0

sementara benar
melakukan 
  echo "Nomor lingkaran:" $((++penghitung))
  tidur 1
selesai

Perintah trap berisi perintah echo dan perintah exit . Ini akan dipicu ketika SIGINT dinaikkan. Sisa skrip adalah loop sederhana. Jika Anda menjalankan skrip dan menekan Ctrl+C, Anda akan melihat pesan dari definisi trap , dan skrip akan berhenti.

 ./sigint.sh 

Menggunakan perangkap dalam skrip untuk menangkap Ctrl+c

Kita dapat menggunakan trap dengan sinyal ERR untuk menangkap kesalahan yang terjadi. Ini kemudian dapat diumpankan ke perintah atau fungsi. Ini adalah "trap.sh." Kami mengirimkan pemberitahuan kesalahan ke fungsi yang disebut error_handler .

 #!/bin/bash

perangkap 'error_handler $? $LINENO' ERR

error_handler() {
  echo "Kesalahan: ($1) terjadi pada $2"
}

utama() {
  echo "Di dalam fungsi utama ()"
  bad_command
  kedua
  ketiga
  keluar $?
}

kedua() {
  echo "Setelah panggilan ke main()"
  echo "Di dalam fungsi kedua ()"
}

ketiga() {
  echo "Di dalam fungsi ketiga ()"
}

utama

Sebagian besar skrip ada di dalam fungsi main , yang memanggil fungsi second dan third . Ketika kesalahan ditemukan—dalam hal ini, karena bad_command tidak ada—pernyataan trap mengarahkan kesalahan ke fungsi error_handler . Ini melewati status keluar dari perintah gagal dan nomor baris ke fungsi error_handler .

 ./trap.sh 

Menggunakan perangkap dengan ERR untuk menangkap kesalahan dalam skrip

Fungsi error_handler kami hanya mencantumkan detail kesalahan ke jendela terminal. Jika mau, Anda dapat menambahkan perintah exit ke fungsi agar skrip dihentikan. Atau Anda dapat menggunakan serangkaian pernyataan if/elif/fi untuk melakukan tindakan yang berbeda untuk kesalahan yang berbeda.

Dimungkinkan untuk memperbaiki beberapa kesalahan, yang lain mungkin mengharuskan skrip untuk berhenti.

Tip Terakhir

Menangkap kesalahan sering kali berarti mendahului hal-hal yang bisa salah, dan memasukkan kode untuk menangani kemungkinan itu jika muncul. Itu selain memastikan alur eksekusi dan logika internal skrip Anda benar.

Jika Anda menggunakan perintah ini untuk menjalankan skrip Anda, Bash akan menunjukkan kepada Anda keluaran jejak saat skrip dijalankan:

 bash -x skrip Anda.sh

Bash menulis keluaran jejak di jendela terminal. Ini menunjukkan setiap perintah dengan argumennya—jika ada. Ini terjadi setelah perintah diperluas tetapi sebelum dieksekusi.

Ini bisa menjadi bantuan luar biasa dalam melacak bug yang sulit dipahami.

TERKAIT: Cara Memvalidasi Sintaks Skrip Bash Linux Sebelum Menjalankannya