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:
shellcheck skrip.shSkrip 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:
#!/bin/bash
nama_file="laporan penting.txt"
if [ -f $nama_file ]; then
echo "file ditemukan"
fiContoh tampilan laporan Shellcheck untuk skrip tersebut (format dapat sedikit berbeda antar versi):
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:
| Kode | Inti pesan | Artinya |
|---|---|---|
| SC2086 | kutip variabelnya | nilai pecah per kata atau terurai sebagai glob |
| SC2148 | tambah shebang | tanpa #!/bin/bash, Shellcheck tidak tahu shell yang dituju |
| SC2034 | variabel tampak tak terpakai | sering pertanda salah ketik nama |
| SC2164 | cd gagal tak tertangani | perintah berikutnya jalan di direktori salah |
Untuk SC2148, contoh tampilan laporannya pada skrip tanpa shebang:
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:
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:
bash: [: data: binary operator expected
uji tanpa kutip: exit 2
uji dengan kutip: file ditemukanMari kita bedah baris demi baris:
- Baris 1-2: membuat file bernama dua kata — wajar untuk nama dokumen.
- Baris 3 (
[ -f $nama ]tanpa kutip): bash memecahdata penting.txtper kata, sehinggatestmenerimadata,penting.txt, dan]sebagai argumen terpisah — error binary operator expected keluar dengan exit code2. - 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:
| Opsi | Efek saat aktif |
|---|---|
set -e | skrip berhenti saat ada perintah gagal (exit code selain 0) |
set -u | variabel tak terdefinisi jadi error fatal, bukan string kosong |
set -o pipefail | pipeline gagal bila ada tahap yang gagal, bukan hanya tahap terakhir |
Tanpa pipefail, pipeline hanya melaporkan exit code perintah terakhir — kegagalan tahap tengah hilang. Bukti:
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:
0
exit pipeline tanpa pipefail: 0
0
exit pipeline dengan pipefail: 1grep 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:
- Shebang di baris pertama —
#!/bin/bash; perilaku konsisten dan SC2148 hilang. - Kutip setiap perluasan —
"$var","$@", dan"${daftar[@]}"aman dari pemisahan kata. - Pilih
[[ ]]di skrip bash — tanpa jebakan pemisahan kata dan mendukung&&/||alami;[ ]sah untuk skrip POSIX sh. - Bandingkan string dengan
=— dalam[ ]hanya=yang POSIX; dalam[[ ]]boleh==. - 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
.