Shell terkenal sangat memaafkan: variabel salah ketik tidak error, variabel tanpa kutip diam-diam pecah menjadi beberapa kata, perintah yang gagal tetap dilanjutkan. Kebajikan itu berubah menjadi bug begitu skrip menangani data nyata. Shellcheck adalah penganalisis statis untuk skrip shell: membaca skrip dan menandai pola berbahaya tanpa menjalankan satu baris pun. Chapter ini membahas cara membaca laporannya, aturan SC yang paling sering muncul, dan konvensi penulisan yang menjaga kualitas skrip.

Apa itu Shellcheck #

Shellcheck menelusuri skrip dengan parser yang memahami aturan bash, lalu mencocokkannya dengan basis aturan bernomor berprefiks SC. Tersedia sebagai paket shellcheck di distro besar (Debian: apt install shellcheck), terintegrasi ke banyak editor, dan bisa dipakai langsung di shellcheck.net . Pemakaiannya sederhana:

bash
shellcheck skrip.sh

Skrip bersih: keluar dengan exit code 0. Ada temuan: laporan muncul dan exit code 1 — cocok sebagai gerbang pemeriksaan otomatis.

Membaca Laporan: Kasus Variabel Tanpa Kutip #

Aturan yang paling sering menyapa adalah SC2086. Perhatikan skrip.sh berikut yang memeriksa keberadaan sebuah file:

bash
#!/bin/bash
nama_file="laporan penting.txt"

if [ -f $nama_file ]; then
  echo "file ditemukan"
fi

Contoh tampilan laporan Shellcheck untuk skrip tersebut (format dapat sedikit berbeda antar versi):

text
In skrip.sh line 4:
if [ -f $nama_file ]; then
         ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: [ -f "$nama_file" ]?

Setiap temuan memuat lokasi, potongan kode dengan penanda, kode aturan beserta tingkatnya (error, warning, info, style), dan penjelasnya. Bila Shellcheck cukup yakin, ia menawarkan perbaikan langsung seperti baris Did you mean di atas — memakai kutip ganda menyelesaikan temuan ini seketika.

Kode SC yang Sering Muncul #

Kode berikut muncul hampir di setiap skrip pemula:

KodeInti pesanArtinya
SC2086kutip variabelnyanilai pecah per kata atau terurai sebagai glob
SC2148tambah shebangtanpa #!/bin/bash, Shellcheck tidak tahu shell yang dituju
SC2034variabel tampak tak terpakaisering pertanda salah ketik nama
SC2164cd gagal tak tertanganiperintah berikutnya jalan di direktori salah

Untuk SC2148, contoh tampilan laporannya pada skrip tanpa shebang:

text
In skrip.sh line 1:
nama="Budi"
^-- SC2148 (warning): Tips depend on target shell and yours is unknown. Add a shebang.

Quoting: Bukti Nyata Word Splitting #

Nasihat SC2086 bukan gaya-gayaan: ketika nilai variabel mengandung spasi, pemisahan kata benar-benar terjadi. Uji [ -f $nama ] di bawah menerima tiga argumen, bukan satu:

bash
printf 'isi\n' > "data penting.txt"
nama="data penting.txt"
[ -f $nama ] 2>&1
echo "uji tanpa kutip: exit $?"
[ -f "$nama" ] && echo "uji dengan kutip: file ditemukan"

Output yang Dihasilkan:

text
bash: [: data: binary operator expected
uji tanpa kutip: exit 2
uji dengan kutip: file ditemukan

Mari kita bedah baris demi baris:

  1. Baris 1-2: membuat file bernama dua kata — wajar untuk nama dokumen.
  2. Baris 3 ([ -f $nama ] tanpa kutip): bash memecah data penting.txt per kata, sehingga test menerima data, penting.txt, dan ] sebagai argumen terpisah — error binary operator expected keluar dengan exit code 2.
  3. Baris 5 ([ -f "$nama" ]): kutip menjaga nilai tetap satu argumen; uji berjalan normal dan file ditemukan.

set -euo pipefail untuk Skrip Serius #

Skrip produksi umumnya membuka dirinya dengan set -euo pipefail. Ketiga simpulnya:

OpsiEfek saat aktif
set -eskrip berhenti saat ada perintah gagal (exit code selain 0)
set -uvariabel tak terdefinisi jadi error fatal, bukan string kosong
set -o pipefailpipeline gagal bila ada tahap yang gagal, bukan hanya tahap terakhir

Tanpa pipefail, pipeline hanya melaporkan exit code perintah terakhir — kegagalan tahap tengah hilang. Bukti:

bash
printf 'apel\n' | grep jeruk | wc -l
echo "exit pipeline tanpa pipefail: $?"
set -o pipefail
printf 'apel\n' | grep jeruk | wc -l
echo "exit pipeline dengan pipefail: $?"

Output yang Dihasilkan:

text
0
exit pipeline tanpa pipefail: 0
0
exit pipeline dengan pipefail: 1

grep jeruk gagal menemukan apa pun, tetapi wc -l tetap sukses mencetak 0 — exit code pipeline pun 0. Setelah pipefail aktif, pipeline yang sama melaporkan 1. Catatan: set -e punya pengecualian — perintah dalam kondisi if maupun rantai &&/|| tidak memicunya. Demo set -u sudah kita praktikkan pada Chapter Debugging Shell Scripts .

Konvensi Penulisan yang Menjaga Kualitas #

Beberapa kebiasaan yang sejalan dengan aturan SC:

  1. Shebang di baris pertama — #!/bin/bash; perilaku konsisten dan SC2148 hilang.
  2. Kutip setiap perluasan — "$var", "$@", dan "${daftar[@]}" aman dari pemisahan kata.
  3. Pilih [[ ]] di skrip bash — tanpa jebakan pemisahan kata dan mendukung &&/|| alami; [ ] sah untuk skrip POSIX sh.
  4. Bandingkan string dengan = — dalam [ ] hanya = yang POSIX; dalam [[ ]] boleh ==.
  5. Fungsi kecil satu tugas — mudah dibaca dan diuji; jebakan klasik shell dirangkum di Bash Pitfalls .

Skrip yang lulus Shellcheck dan dibuka set -euo pipefail siap dipercaya bekerja tanpa pengawasan. Tinggal satu pertanyaan: jam berapa ia harus berjalan? Penjadwalannya dibahas pada Chapter Scheduling Scripts .