GNU/Linux >> Belajar Linux >  >> Linux

Cara Men-debug Skrip Bash Di Linux Dan Unix

Debugging membantu Anda memperbaiki kesalahan dalam program Anda. Pada artikel ini, kita akan membahas berbagai metode untuk men-debug skrip bash di sistem operasi Linux dan Unix.

Pengantar

Pada hari-hari awal saya pemrograman, saya telah menghabiskan berjam-jam mencoba menemukan kesalahan dalam kode saya, dan pada akhirnya, itu mungkin sesuatu yang sederhana. Anda mungkin juga menghadapi situasi yang sama.

Mengetahui cara menggunakan teknik debugging yang tepat akan membantu Anda memecahkan kesalahan dengan cepat. Tidak seperti bahasa lain seperti Python, Java, dll. Tidak ada alat debugger untuk bash di mana Anda dapat mengatur breakpoint, kode langkah, dll.

Ada beberapa fitur bawaan yang membantu men-debug skrip bash shell. Kita akan melihat secara detail fitur-fitur tersebut di bagian yang akan datang.

Tiga cara menggunakan opsi Debugging

Saat Anda ingin mengaktifkan opsi debugging di skrip Anda, Anda dapat melakukannya dengan tiga cara.

1 . Aktifkan opsi debug dari shell terminal saat memanggil skrip.

$ bash [ debugging flags ] scriptname

2 . Aktifkan opsi debug dengan meneruskan tanda debug ke baris shebang di skrip.

#!/bin/bash [ debugging flags ]

3 . Aktifkan opsi debugging dengan menggunakan set perintah dari skrip.

set -o nounset
set -u

Untuk apa perintah Set digunakan?

set command adalah perintah bawaan shell yang dapat digunakan untuk mengontrol parameter bash dan mengubah perilaku bash dengan cara tertentu.

Biasanya Anda tidak akan menjalankan perintah set dari terminal untuk mengubah perilaku shell Anda. Ini akan digunakan secara luas dalam skrip shell baik untuk debugging atau untuk mengaktifkan mode bash ketat.

$ type -a set
set is a shell builtin

Anda dapat mengakses bagian bantuan dari perintah set untuk mengetahui flag apa yang didukungnya dan apa yang dilakukan setiap flag.

$ set --help

Debug bagian dari skrip atau skrip lengkap

Sebelum mempelajari tentang opsi debug, Anda harus memahami bahwa Anda dapat men-debug seluruh skrip atau hanya bagian tertentu dari kode. Anda harus menggunakan perintah set untuk mengaktifkan dan menonaktifkan opsi debugging.

  • set -<debugging-flag> akan mengaktifkan mode debug.
  • set +<debugging-flag> akan menonaktifkan mode debug.

Lihatlah kode di bawah ini. set -x akan mengaktifkan mode xtrace untuk skrip dan set +x akan menonaktifkan mode xtrace. Apa pun yang berada di antara set -x dan set +x akan berjalan dalam mode debug xtrace.

Anda akan belajar tentang mode xtrace di bagian yang akan datang. Jadi untuk setiap tanda debug, satu-satunya hal yang harus Anda ingat adalah, set - akan mengaktifkan mode dan set + akan menonaktifkan mode.

#!/bin/bash

set -x
read -p "Pass Dir name : " D_OBJECT
read -p "Pass File name : " F_OBJECT
set +x

touch ${D_OBJECT}/${F_OBJECT}

Gagal jika tidak ada variabel yang ditentukan

Saat bekerja dengan variabel di bash , kelemahannya adalah jika kita mencoba menggunakan variabel yang tidak ditentukan, skrip tidak akan gagal dengan beberapa pesan kesalahan seperti "Variabel tidak ditentukan" . Sebaliknya itu akan mencetak string kosong.

Lihatlah kode di bawah ini di mana saya mendapatkan input dari pengguna dan menyimpannya di variabel $OBJECT . Saya mencoba menjalankan operator pengujian (-f dan -d ) pada $OBJECT1 variabel yang tidak didefinisikan.

#!/bin/bash

read -p "Please provide the object name :  " OBJECT
if [[ -f $OBJECT1 ]]
then
    echo "$OBJECT is a file"
elif [[ -d $OBJECT1 ]]
then
    echo "$OBJECT is a directory"
fi

Ketika saya menjalankan kode ini, seharusnya saya membuat kesalahan tetapi tidak dan bahkan skrip keluar dengan kode pengembalian nol.

Untuk mengganti perilaku ini, gunakan -u flag yang akan memunculkan kesalahan saat variabel yang tidak ditentukan digunakan.

Saya akan menjalankan kode yang sama lagi dengan nama variabel yang salah tetapi kali ini akan memunculkan "Variabel tidak terikat" kesalahan.

Anda juga dapat mengatur -u opsi menggunakan set perintahkan atau berikan sebagai argumen ke shebang.

set -u
set -o nounset

(atau)

#! /bin/bash -u

Mode Xtrace untuk menyelamatkan

Ini adalah mode yang saya gunakan secara luas ketika saya men-debug skrip bash untuk kesalahan logis. Xtrace mode akan menampilkan kode baris demi baris tetapi dengan parameter yang diperluas.

Di bagian sebelumnya ketika saya menjalankan kode tanpa -u flag, itu berhasil diselesaikan tetapi saya mengharapkan output di terminal. Sekarang saya dapat menjalankan skrip yang sama dalam mode xtrace dan melihat dengan tepat di mana masalah terjadi dalam skrip.

Perhatikan contoh kode berikut.

#!/bin/bash

read -p "Please provide the object name :  " OBJECT
if [[ -f $OBJECT1 ]]
then
    echo "$OBJECT is a file"
elif [[ -d $OBJECT1 ]]
then
    echo "$OBJECT is a directory"
fi

Ketika saya menjalankan kode di atas, saya tidak menghasilkan apa-apa.

Untuk men-debug masalah ini, saya dapat menjalankan skrip di xtrace mode dengan meneruskan -x bendera.

Pada output di bawah ini, Anda dapat melihat variabel diperluas dan dicetak. Ini memberitahu saya bahwa ada string kosong yang ditetapkan ke pernyataan kondisional -f dan -d . Dengan cara ini saya dapat memeriksa dan memperbaiki kesalahan secara logis.

Tanda plus yang Anda lihat di output dapat diubah dengan mengatur PS4 variabel dalam skrip. Secara default, PS4 diatur ke (+ ).

$ echo $PS4
+
$ PS4=" ==> " bash -x debugging.sh

Anda juga dapat mengatur mode Xtrace menggunakan perintah set atau meneruskannya sebagai argumen ke shebang.

set -x
set -o xtrace

(atau)

#! /bin/bash -x

Demikian pula, saat melakukan debug, Anda dapat mengarahkan log debug Xtrace ke file alih-alih mencetaknya ke terminal.

Lihatlah kode di bawah ini. Saya menetapkan deskriptor file 6 ke .log file dan BASH_XTRACEFD="6" akan mengarahkan log debug xtrace ke deskriptor file 6.

#!/bin/bash


exec 6> redirected_debug.log 
PS4=' ==> ' 
BASH_XTRACEFD="6" 
read -p "Please provide the object name :  " OBJECT
if [[ -f $OBJECT1 ]]
then
    echo "$OBJECT is a file"
elif [[ -d $OBJECT1 ]]
then
    echo "$OBJECT is a directory"
fi

Ketika saya menjalankan kode ini alih-alih mencetak keluaran xtrace di terminal, kode itu akan diarahkan ke .log berkas.

$ cat redirected_debug.log 
==> read -p 'Please provide the object name :  ' OBJECT
==> [[ -f '' ]]
==> [[ -d '' ]]

Status keluar PIPA

Perilaku default saat menggunakan pipa adalah akan mengambil kode keluar dari perintah run terakhir di pipa. Bahkan jika perintah sebelumnya di pipa gagal, itu akan menjalankan sisa pipa.

Lihatlah contoh di bawah ini. Saya mencoba membuka file yang tidak tersedia dan mengirimkannya dengan jumlah kata program. Meskipun cat perintah melempar kesalahan, program penghitungan kata berjalan.

Jika Anda mencoba memeriksa kode keluar dari perintah pipa yang dijalankan terakhir menggunakan $? , Anda akan mendapatkan nol sebagai kode keluar yang berasal dari program penghitungan kata.

$ cat nofile.txt | wc -l
cat: nofile.txt: No such file or directory
0
$ echo $?
0

Ketika pipefail diaktifkan di skrip, jika ada perintah yang melempar kode pengembalian bukan nol ke dalam pipa, itu akan dianggap sebagai kode pengembalian untuk seluruh pipa. Anda dapat mengaktifkan pipefail dengan menambahkan properti set berikut di skrip Anda.

set -o pipefail

Masih ada masalah dengan pendekatan ini. Biasanya yang diharapkan adalah jika ada perintah di pipa yang gagal, maka skrip harus keluar tanpa menjalankan sisa perintah di pipa.

Namun sayangnya, bahkan jika ada perintah yang gagal, perintah berikutnya di pipa berjalan. Ini karena setiap perintah dalam pipa berjalan di subkulitnya sendiri. Shell akan menunggu sampai semua proses dalam pipa selesai kemudian mengembalikan hasilnya.

Mode Ketat Bash

Untuk menghilangkan semua kemungkinan kesalahan yang telah kita lihat di bagian sebelumnya, disarankan untuk menambahkan opsi berikut di setiap skrip.

Kami telah membahas semua opsi ini di bagian sebelumnya secara mendetail.

  • -e flag => Keluar dari skrip jika ada perintah yang mengeluarkan kode keluar Non-Zero.
  • -u flag => Buat skrip gagal jika nama variabel yang tidak ditentukan digunakan.
  • pipefail => Jika ada perintah dalam pipeline yang gagal maka kode keluar akan dipertimbangkan untuk keseluruhan pipeline.
  • IFS => Pemisah bidang internal, menyetelnya ke baris baru(\n) dan (\t) akan membuat pemisahan hanya terjadi di baris dan tab baru.
set -e
set -u
set -o pipefail

Atau

set -euo pipefail
IFS=$'\n\t'

Tangkap sinyal menggunakan TRAP

Perangkap memungkinkan Anda untuk menangkap sinyal ke skrip bash Anda dan mengambil beberapa tindakan yang sesuai.

Pikirkan skenario di mana Anda memicu skrip tetapi Anda ingin membatalkan skrip menggunakan CTRL+C penekanan tombol. Dalam hal ini, SIGINT akan dikirim ke skrip Anda. Anda dapat menangkap sinyal ini dan menjalankan beberapa perintah atau fungsi.

Lihatlah kode semu yang diberikan di bawah ini. Saya telah membuat fungsi yang disebut pembersihan yang akan berjalan ketika SIGINT diteruskan ke skrip.

trap 'cleanup' TERM INT
function cleanup(){
    echo "Running cleanup since user initiated CTRL + C"
    <some logic>
}

Anda dapat menggunakan trap "DEBUG", yang dapat digunakan untuk mengeksekusi pernyataan berulang kali dalam skrip. Cara berperilaku adalah untuk setiap pernyataan yang berjalan di perangkap skrip akan menjalankan fungsi atau pernyataan terkait.

Anda dapat memahaminya menggunakan contoh di bawah ini.

#!/bin/bash

trap 'printf "${LINENO} ==> DIR_NAME=${D_OBJECT} ; FILE_NAME=${F_OBJECT}; FILE_CREATED=${FILE_C} \n"' DEBUG

read -p "Pass Dir name : " D_OBJECT
read -p "Pass File name : " F_OBJECT

touch ${D_OBJECT}/${F_OBJECT} && FILE_C="Yes"
exit 0

Ini adalah program sederhana yang mendapatkan input pengguna dan membuat file dan direktori. Perintah trap akan dijalankan untuk setiap pernyataan dalam skrip dan akan mencetak argumen yang diteruskan dan status pembuatan file.

Lihat output di bawah ini. Untuk setiap baris dalam skrip, jebakan dipicu dan variabel diperbarui sesuai dengan itu.

Cetak kode menggunakan mode Verbose

Dalam mode verbose, kode akan dicetak sebelum mengembalikan hasilnya. Jika program memerlukan input interaktif, maka baris itu sendiri yang akan dicetak diikuti oleh blok kode.

Perhatikan program berikut. Ini adalah program sederhana yang mendapatkan objek dari pengguna dan memeriksa apakah objek yang diteruskan adalah file atau direktori menggunakan pernyataan bersyarat .

#!/bin/bash

read -p "Please provide the object name :  " OBJECT
if [[ -f $OBJECT ]]
then
  echo "$OBJECT is a file"
elif [[ -d $OBJECT ]]
then
  echo "$OBJECT is a directory"
fi

Ketika saya menjalankan kode di atas, pertama akan mencetak kode kemudian menunggu input pengguna seperti yang ditunjukkan di bawah ini.

Setelah saya melewati objek, maka sisa kode akan dicetak diikuti oleh output.

Anda juga dapat mengatur mode verbose menggunakan set atau di shebang .

set -v
set -o verbose

(atau)

#! /bin/bash -v

Anda juga dapat menggabungkan mode verbose dengan mode lain.

set -vx # Verbose and Xtrace Mode
set -uv # Verbose and Unset Mode

Validasi sintaks - mode noexec

Sampai sekarang kita telah melihat bagaimana bekerja dengan kesalahan logis dalam skrip. Di bagian ini, mari kita bahas tentang kesalahan sintaks.

Kesalahan sintaks sangat umum dalam program. Anda mungkin melewatkan kutipan atau gagal keluar dari loop, dll. Anda dapat menggunakan "-n " bendera yang disebut noexec mode untuk memvalidasi sintaks sebelum menjalankan program.

Saya akan menjalankan potongan kode di bawah ini dan memvalidasi sintaks.

#!/bin/bash

TOOLS=( htop peek tilix vagrant shutter )
for TOOL in "${TOOLS[@]" 
do
    echo "--------------INSTALLING: ${TOOL}---------------------------"
    apt install ${TOOL} -y
#done

Ada dua kesalahan dalam program ini. Pertama, saya gagal menutup kurung kurawal di "for loop " dan kedua done kata kunci dikomentari yang seharusnya menandai akhir dari perulangan.

Ketika saya menjalankan program ini, saya mendapatkan pesan kesalahan berikut yang menunjuk ke kurung kurawal missing dan kata kunci selesai . Terkadang nomor baris yang ditunjukkan dalam pesan kesalahan tidak berisi kesalahan apa pun yang harus Anda gali untuk menemukan kesalahan yang sebenarnya.

$ bash -n ./debugging.sh 

./debugging.sh: line 6: unexpected EOF while looking for matching `"'
./debugging.sh: line 8: syntax error: unexpected end of file

Perlu dicatat bahwa, secara default ketika Anda menjalankan skrip, bash akan memvalidasi sintaks dan membuang kesalahan ini bahkan tanpa menggunakan mode noexec.

Atau, Anda juga dapat menggunakan set perintah atau shebang untuk menggunakan noexec modus.

set -n 
set -o noexec

Atau,

#! /bin/bash -n

Ada beberapa alat eksternal di luar sana yang layak digunakan untuk men-debug skrip. Salah satu alat tersebut adalah Shellcheck . Shellcheck juga dapat diintegrasikan dengan editor teks populer seperti vscode, sublime text, Atom.

Kesimpulan

Pada artikel ini, saya telah menunjukkan kepada Anda beberapa cara untuk men-debug skrip bash. Tidak seperti bahasa pemrograman lain, bash tidak memiliki alat debug selain beberapa opsi bawaan. Terkadang opsi debug bawaan ini akan lebih dari cukup untuk menyelesaikan pekerjaan.

Panduan pembuatan skrip Bash:

  • Skrip Bash – Mengurai Argumen Dalam Skrip Bash Menggunakan getopts
  • Cara Membuat Kotak Dialog GUI Dalam Skrip Bash Dengan Zenity Di Linux Dan Unix
  • Skrip Bash – Pernyataan Kasus
  • Skrip Bash – Pernyataan Bersyarat
  • Skrip Bash – Manipulasi String
  • Bash Scripting – Perintah Printf Dijelaskan Dengan Contoh
  • Bash Scripting – Array Terindeks Dijelaskan Dengan Contoh
  • Bash Scripting – Array Asosiatif Dijelaskan Dengan Contoh
  • Skrip Bash – Untuk Pengulangan Dijelaskan Dengan Contoh
  • Bash Scripting – Sementara Dan Sampai Perulangan Dijelaskan Dengan Contoh
  • Pengalihan Bash Dijelaskan Dengan Contoh
  • Bash Scripting – Variabel Dijelaskan Dengan Contoh
  • Bash Scripting – Fungsi Dijelaskan Dengan Contoh
  • Perintah Bash Echo Dijelaskan Dengan Contoh Di Linux
  • Tutorial Bash Heredoc Untuk Pemula

Linux
  1. Cara Mengatur Alamat IP Statis dan Konfigurasi Jaringan di Linux

  2. Cara Mengatur, Mendaftar, dan Menghapus Variabel Lingkungan di Linux

  3. UNIX / Linux :Cara menginstal dan mengkonfigurasi mutt

  1. Cara Mengatur dan Mendaftar Variabel Lingkungan di Linux

  2. Cara Mengatur/Membuat Variabel Lingkungan dan Shell di Linux

  3. Bagaimana cara mengatur $PATH secara permanen di Linux/Unix?

  1. Cara Memasang dan Mengatur Tor Browser di Linux

  2. Cara Mengatur dan Mendaftar Variabel Lingkungan di Linux

  3. Cara Membuat Kotak Dialog GUI Dalam Skrip Bash Dengan Zenity Di Linux Dan Unix