Semakin panjang skrip, semakin banyak tempat yang bisa salah — dan bug di shell punya kebiasaan buruk: diam. Variabel yang salah ketik menjadi string kosong, perintah yang gagal tertelan alur, loop berputar lebih banyak dari rencana tanpa protes. Untung bash membawa peralatan debugging bawaan: mode xtrace yang mencatat setiap langkah, pemeriksaan sintaks tanpa menjalankan skrip, dan mode ketat yang mengubah kejadian diam-diam menjadi error keras. Chapter ini mempraktikkan semuanya pada skrip kecil yang sengaja diberi masalah.

Mengikuti Jejak Eksekusi dengan bash -x #

Opsi bash -x menyalakan xtrace: setiap perintah dicetak ke stderr sebelum dieksekusi, diawali tanda +. Jejak ini keluar lewat stderr, jadi 2>&1 kita pakai untuk menyatukannya dengan output normal dalam satu tampilan. Kedua jalankan berikut sama-sama menelusuri hitung.sh; jalankan kedua memakai variabel PS4 — prefiks jejak yang bisa kita kustom — untuk menambah nomor baris:

bash
cat > hitung.sh <<'AKHIR'
#!/bin/bash
total=0
for n in 10 20 30; do
  total=$((total + n))
done
echo "total: $total"
AKHIR
bash -x hitung.sh 2>&1
PS4='baris $LINENO: ' bash -x hitung.sh 2>&1

Output yang Dihasilkan:

text
+ total=0
+ for n in 10 20 30
+ total=10
+ for n in 10 20 30
+ total=30
+ for n in 10 20 30
+ total=60
+ echo 'total: 60'
total: 60
baris 2: total=0
baris 3: for n in 10 20 30
baris 4: total=10
baris 3: for n in 10 20 30
baris 4: total=30
baris 3: for n in 10 20 30
baris 4: total=60
baris 6: echo 'total: 60'
total: 60

Ada tiga hal penting yang terlihat pada jejak di atas:

  1. Nilai sudah diekspansi: yang tercatat total=10, bukan total=$((total + n)) — kita melihat nilai sesungguhnya yang dipegang variabel pada tiap langkah, bukan rumusnya.
  2. Argumen diberi kutip: jejak echo 'total: 60' menandai argumen dengan kutip, sehingga spasi tersembunyi dalam string langsung kelihatan.
  3. $LINENO menunjuk baris skrip: prefiks baris 4: pada jalankan kedua memberi tahu baris mana yang sedang jalan — saat skrip besar tersesat, nomor baris menghemat banyak waktu.

Melacak Hanya Segmen Mencurigakan #

Jejak penuh membanjiri layar bila skripnya panjang. Builtin set -x menyalakan trace di tengah skrip dan set +x mematikannya, sehingga kita bisa membungkus segmen yang mencurigakan saja:

bash
cat > segmen.sh <<'AKHIR'
#!/bin/bash
a=5
b=3
set -x
hasil=$((a * b))
set +x
echo "hasil: $hasil"
AKHIR
bash segmen.sh 2>&1

Output yang Dihasilkan:

text
+ hasil=15
+ set +x
hasil: 15

Hanya baris di antara set -x dan set +x yang terlacak — penugasan a dan b tidak muncul. Baris + set +x ikut tercatat sekali karena perintah itu sendiri masih berada dalam mode trace ketika dieksekusi; setelahnya layar kembali bersih. Bila hasil segmen ini benar, geser jendela trace ke segmen berikutnya.

Memeriksa Sintaks tanpa Menjalankan #

Opsi -n membuat bash membaca dan mem-parse skrip tanpa menjalankan satu baris pun. Pemeriksaan ini menangkap pasangan if/fi, for/done, dan kutip yang tidak tertutup — sebelum skrip menyentuh file apa pun:

bash
cat > rusak.sh <<'AKHIR'
#!/bin/bash
for i in 1 2 3; do
  echo "angka $i"
AKHIR
bash -n rusak.sh 2>&1

Output yang Dihasilkan:

text
rusak.sh: line 4: syntax error: unexpected end of file

Skrip rusak.sh kehilangan done, sehingga parser kehabisan file — dilaporkan sebagai unexpected end of file pada baris terakhirnya. Karena tidak ada yang dieksekusi, bash -n aman dipakai untuk menyetir skrip yang menyentuh data penting: kesalahan sintaks ketahuan tanpa efek samping.

Menangkap Variabel Salah Ketik dengan set -u #

Di bash, variabel yang belum diisi bernilai string kosong — nama yang salah ketik pun tidak menghasilkan error, hanya hasil yang salah. Opsi set -u (nounset) mengubah pemakaian variabel tak terdefinisi menjadi error fatal:

bash
cat > salah.sh <<'AKHIR'
#!/bin/bash
echo "nama: $NAMAA"
AKHIR
bash -u salah.sh 2>&1

Output yang Dihasilkan:

text
salah.sh: line 2: NAMAA: unbound variable

$NAMAA adalah salah ketik dari $NAMA. Tanpa -u, skrip hanya mencetak nama: kosong dan berlanjut seolah tidak terjadi apa-apa; dengan -u, bash menyebut nama variabel bermasalah beserta barisnya lalu berhenti. Untuk skrip serius, letakkan set -u di baris kedua setelah shebang agar perlindungan ini aktif sejak awal.

Debugging Manual dengan echo #

Peralatan tertua tetap efektif: sematkan echo penanda — misalnya echo "sampai sini 1" — untuk memetakan sejauh mana eksekusi berjalan sebelum keanehan terjadi. Untuk memeriksa isi variabel, cetak dengan pembatas yang terlihat, misalnya printf '[%s]\n' "$nama", sehingga spasi di awal atau akhir nilainya langsung ketahuan. Perpaduan favorit banyak penulis skrip: set -u untuk menutup jebakan variabel kosong, ditambah bash -x saat perilakunya tetap misterius.

Semua peralatan di atas mengamati skrip yang sedang berjalan. Bagaimana bila kita ingin pola-pola berbahaya ditandai sebelum skrip dieksekusi sama sekali? Untuk itu ada penganalisis statis — Chapter Shellcheck dan Script Quality .