Shell Scripting Dasar — DevOps

Apa itu Shell Script? Shell script adalah file berisi kumpulan command yang dieksekusi secara berurutan. Berguna untuk mengotomasi tugas repetitif seperti…

Shell script adalah file berisi perintah yang dijalankan bash dari atas ke bawah, persis seperti kalau kamu mengetiknya satu per satu. Di server, script paling penting adalah script deploy: ambil kode baru, pasang dependensi, migrasi database, restart app. Bayangin checklist pilot sebelum terbang: kalau satu cek gagal, pesawatnya gak boleh lepas landas. Script deploy yang baik juga begitu: begitu satu langkah gagal, dia berhenti dan bilang gagal. Dasar script (shebang, variabel, if, $?) ada di pelajaran Shell Scripts Dasar, track Terminal.

🧪 Tebakan cepat: deploy.sh milik catatan-api ditulis tanpa set -e. Saat deploy, GitHub gak bisa dihubungi, jadi git pull gagal. Baris terakhir yang tercetak apa, dan exit code script-nya berapa? Tebak dulu, jawabannya ada di bagian "Exit code: 0 berhasil, selain 0 gagal".

deploy.sh untuk catatan-api

#!/bin/bash
set -euo pipefail

APP_DIR="/srv/catatan-api"
BRANCH="${1:-main}"

echo "Deploying catatan-api from branch $BRANCH"
cd "$APP_DIR"
git pull --ff-only origin "$BRANCH"
npm ci --omit=dev
node migrate.js | tee -a deploy.log
sudo systemctl restart catatan-api
echo "Deploy complete!"

Sekali saja: chmod u+x deploy.sh (pelajaran File System & Permissions), lalu jalankan dengan ./deploy.sh.

Exit code: 0 berhasil, selain 0 gagal

Setiap perintah selesai dengan exit code: 0 artinya berhasil, angka lain artinya gagal. git memakai 128 untuk error fatal. echo $? mencetak exit code perintah terakhir. Ini deploy.sh yang sama, tanpa baris set, saat GitHub gak bisa dihubungi:

deploy@web-1:/srv/catatan-api$ ./deploy.sh
Deploying catatan-api from branch main
ssh: connect to host github.com port 22: Connection timed out
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

added 64 packages, and audited 65 packages in 3s

found 0 vulnerabilities
Tidak ada migrasi baru.
Deploy complete!
deploy@web-1:/srv/catatan-api$ echo $?
0

git pull gagal dengan exit 128, tapi bash cuma lanjut ke baris berikutnya. npm ci memasang ulang kode lama, app di-restart dengan kode lama, lalu script mencetak Deploy complete! dan keluar dengan 0, karena exit code script adalah exit code perintah terakhirnya, echo. Itu jawaban tebakannya. CI atau rekan setim yang membaca exit code-nya mengira deploy berhasil.

set -euo pipefail: tiga pengaman

Dengan set -euo pipefail di baris kedua, kejadian yang sama berhenti di tempat:

deploy@web-1:/srv/catatan-api$ ./deploy.sh
Deploying catatan-api from branch main
ssh: connect to host github.com port 22: Connection timed out
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
deploy@web-1:/srv/catatan-api$ echo $?
128
Pengaman Yang ditangkap di deploy.sh Tanpa pengaman ini
-e git pull gagal: script berhenti di baris 9, exit 128 jalan terus sampai Deploy complete!
-u salah ketik $BRANH: ./deploy.sh: line 7: BRANH: unbound variable, exit 1 $BRANH diam-diam jadi teks kosong
-o pipefail node migrate.js gagal di dalam pipe: berhenti di baris 11, exit 1 pipe dianggap sukses karena tee sukses

Kutip setiap variabel

Tanpa kutip, bash memecah isi variabel di spasi sebelum menjalankan perintahnya:

LOG="storage/logs/deploy 2026-10-09.log"
touch $LOG     # dua file: "storage/logs/deploy" dan "2026-10-09.log"
touch "$LOG"   # satu file, persis namanya

Biasakan "$APP_DIR", "$BRANCH", "$file". Kutip dua tetap mengganti variabel dengan isinya, kutip satu ('$APP_DIR') gak.

Loop: tunggu app siap

Setelah restart, app butuh beberapa detik. for menjalankan isinya sekali untuk tiap item:

for i in 1 2 3 4 5; do
  if curl -fsS http://127.0.0.1:3000/health > /dev/null; then
    echo "Health check OK"
    exit 0
  fi
  sleep 2
done
echo "Health check gagal setelah 5 kali" >&2
exit 1

Di latihan: membuat script dengan JavaScript

generateDeployScript(config) menyusun teks script dari array baris yang digabung dengan "\n": shebang #!/bin/bash, set -euo pipefail, satu echo dengan nama app dan branch, semua langkah dari config.steps (pakai spread ...config.steps), lalu echo "Deploy complete!".

⚠️ Jebakan yang sering ketemu

TL;DR: Script deploy dimulai dengan shebang #!/bin/bash (atau #!/usr/bin/env bash) dan set -euo pipefail: -e berhenti di perintah gagal pertama, -u menolak variabel yang belum diisi, -o pipefail membuat pipe gagal kalau salah satu bagiannya gagal. Exit code 0 berarti berhasil, selain 0 gagal, echo $? menampilkannya, dan tanpa -e script yang gagal tetap keluar dengan 0 dari echo terakhirnya. Variabel ditulis NAMA="nilai" tanpa spasi dan dibaca "$NAMA" berkutip, "${1:-main}" memberi nilai cadangan. for x in ...; do ...; done mengulang untuk tiap item. sudo di script butuh aturan NOPASSWD untuk perintah itu saja.

Yang akan kamu pelajari