Shell Script Dry Run dan Approval Gate untuk Perubahan Aman di Linux Production

Last updated on


Target keyword: shell script dry run linux production
Search intent: Problem-solving / Best-practice
Monthly keyword cluster: linux shell scripting, production automation safety, change management devops, incident prevention
Weekly intent rotation: Implementation guide (step-by-step + checklist operasional)

Kalau kamu pernah deg-degan sebelum jalanin script di server production, kamu nggak sendiri.

Masalahnya bukan di “bisa jalan atau nggak”, tapi di dampaknya: salah hapus file, salah restart service, salah update config, atau script nembak host yang nggak seharusnya. Dan seringnya error kayak gini bukan karena engineer nggak jago, tapi karena guardrail-nya belum ada.

Di artikel ini, kita bahas dua pola yang simpel tapi powerful:

  1. Dry run → script menampilkan perubahan yang akan dilakukan tanpa benar-benar eksekusi.
  2. Approval gate → script berhenti di titik kritikal dan minta konfirmasi sebelum lanjut.

Kalau diterapkan bener, dua pola ini bisa nurunin risiko human error secara signifikan, terutama buat tim kecil yang pegang banyak sistem sekaligus.

Kenapa dry run dan approval gate penting di production?

Di production, banyak perubahan terlihat “kecil” tapi efeknya bisa besar:

  • update permission file config
  • rotate secret/env
  • restart service yang lagi high traffic
  • cleanup directory log/temp yang salah path

Pola lama yang berbahaya biasanya begini:

  • script langsung execute
  • minim logging
  • nggak ada preview
  • nggak ada titik verifikasi manusia

Akhirnya pas kejadian, investigasi susah: sebenarnya script ngapain dulu?

Dengan dry run + approval gate:

  • kamu bisa lihat rencana perubahan dulu
  • bisa validasi target host/path/service
  • bisa “nahan” langkah berisiko tinggi
  • dokumentasi perubahan jadi lebih rapi (karena output script jelas)

Prasyarat

  • Linux dengan Bash 4+
  • Akses user yang sesuai (jangan root permanen kalau nggak perlu)
  • Paham basic command: cp, mv, systemctl, sed, grep

Opsional tapi recommended:

  • flock untuk mencegah job tumpang tindih
  • logger terstruktur (JSON line) untuk audit trail

Desain pola: plan → preview → approve → apply

Supaya aman dan konsisten, pakai alur ini:

  1. Plan: kumpulkan aksi yang akan dijalankan
  2. Preview: tampilkan detail (dry run)
  3. Approve: minta konfirmasi jika aksi high-impact
  4. Apply: eksekusi dan log hasil

Jangan campur plan dan apply dalam satu langkah. Kalau logic langsung eksekusi saat generate rencana, dry run jadi nggak bermakna.

Contoh implementasi shell script

Di bawah ini template yang bisa langsung kamu adaptasi.

#!/usr/bin/env bash
set -euo pipefail

DRY_RUN=true
AUTO_APPROVE=false

log() {
  local level="$1"; shift
  printf '[%s] [%s] %s\n' "$(date -Is)" "$level" "$*"
}

usage() {
  cat <<EOF
Usage: $0 [--apply] [--yes]
  --apply   Jalankan perubahan sungguhan (default: dry run)
  --yes     Auto-approve langkah kritikal (hati-hati)
EOF
}

parse_args() {
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --apply)
        DRY_RUN=false
        shift
        ;;
      --yes)
        AUTO_APPROVE=true
        shift
        ;;
      -h|--help)
        usage
        exit 0
        ;;
      *)
        log ERROR "Argumen tidak dikenal: $1"
        usage
        exit 1
        ;;
    esac
  done
}

approve_or_exit() {
  local prompt="$1"

  if [[ "$AUTO_APPROVE" == "true" ]]; then
    log WARN "Auto-approve aktif: $prompt"
    return 0
  fi

  read -r -p "$prompt ketik 'yes' untuk lanjut: " ans
  [[ "$ans" == "yes" ]] || {
    log INFO "Dibatalkan oleh user"
    exit 1
  }
}

run_cmd() {
  local cmd="$*"
  if [[ "$DRY_RUN" == "true" ]]; then
    log INFO "[DRY-RUN] $cmd"
  else
    log INFO "[APPLY] $cmd"
    eval "$cmd"
  fi
}

main() {
  parse_args "$@"

  local config_file="/etc/myapp/app.conf"
  local backup_file="/etc/myapp/app.conf.bak.$(date +%F-%H%M%S)"

  log INFO "Mode: $( [[ "$DRY_RUN" == "true" ]] && echo DRY-RUN || echo APPLY )"

  # Plan + preview
  run_cmd "cp $config_file $backup_file"
  run_cmd "sed -i 's/^MAX_WORKERS=.*/MAX_WORKERS=8/' $config_file"

  # Approval gate sebelum restart service
  approve_or_exit "Akan restart service myapp."
  run_cmd "systemctl restart myapp"
  run_cmd "systemctl is-active --quiet myapp"

  log INFO "Selesai"
}

main "$@"

Cara pakai

Preview dulu (aman):

./safe-change.sh

Apply sungguhan:

./safe-change.sh --apply

Apply + auto-approve (misalnya di CI yang sudah punya guardrail lain):

./safe-change.sh --apply --yes

Kapan wajib pasang approval gate?

Semua aksi nggak perlu approval manual. Kalau kebanyakan gate, workflow malah lambat. Pakai gate untuk aksi dengan blast radius tinggi:

  • restart/stop service production
  • rotate secret atau credential
  • perubahan firewall/routing
  • delete file di path kritikal (/etc, /var/lib, data directory)
  • migration database yang tidak backward compatible

Untuk aksi low-risk (mis. cleanup cache non-kritis), cukup dry run + logging + rollback plan.

Best practice biar nggak “aman semu”

1) Default harus dry run

Jangan kebalik. Kalau default langsung apply, satu typo argumen bisa fatal.

2) Tampilkan konteks sebelum approval

Sebelum prompt “yes/no”, tampilkan:

  • host target
  • service target
  • file/path yang diubah
  • ringkas perintah utama

Approval tanpa konteks = checkbox doang.

3) Wajib ada backup/rollback

Minimal:

  • backup file sebelum edit
  • kalau health check gagal, restore backup
  • log status rollback (sukses/gagal)

4) Jangan pakai eval sembarangan

Di contoh di atas, eval dipakai biar mudah dipahami. Untuk produksi, lebih aman pakai array command atau fungsi spesifik supaya mengurangi command injection risk.

5) Integrasikan dengan lock

Kalau script bisa dipanggil dari cron/CI, pakai flock biar tidak saling tabrak:

flock -n /tmp/safe-change.lock ./safe-change.sh --apply

Troubleshooting umum

Masalah 1: “Dry run terlihat benar, tapi apply gagal”

Penyebab umum:

  • permission beda antar user
  • environment variable beda antar shell
  • dependency command tidak tersedia

Solusi:

  • jalankan dry run dan apply dengan user yang sama
  • validasi command dependency di awal script
  • print environment penting (whoami, hostname, pwd) di log

Masalah 2: “Approval gate ke-skip padahal harusnya tampil”

Penyebab umum:

  • --yes tidak sengaja ikut dari wrapper CI
  • variabel default tertimpa env (AUTO_APPROVE=true)

Solusi:

  • print konfigurasi runtime saat startup
  • batasi --yes hanya di environment tertentu
  • tambahkan guard: kalau host=production dan source bukan pipeline resmi, tolak auto-approve

Masalah 3: “Terlalu banyak prompt, tim jadi malas”

Solusi:

  • klasifikasikan aksi: low/medium/high risk
  • approval manual hanya untuk high risk
  • sisanya cukup dry run + observability

Checklist implementasi

  • Default script adalah dry run
  • Ada flag eksplisit --apply untuk eksekusi nyata
  • Ada approval gate untuk aksi high-impact
  • Ada backup + rollback minimal
  • Log mencatat mode, target, dan hasil
  • Ada lock file untuk mencegah overlap job
  • Sudah diuji di staging sebelum production

FAQ

1) Apakah dry run saja sudah cukup untuk production?

Belum tentu. Dry run bagus untuk preview, tapi untuk aksi berisiko tinggi tetap perlu approval gate, backup, dan rollback plan.

2) Kapan saya boleh pakai --yes (auto-approve)?

Boleh kalau pipeline kamu sudah ketat: ada testing, environment guard, audit log, dan scope perubahan jelas. Untuk eksekusi manual di production, sebaiknya tetap minta konfirmasi.

3) Gimana cara bikin approval gate yang tidak mengganggu kecepatan tim?

Pisahkan aksi berdasarkan risiko. Manual approval hanya untuk high-impact, sementara low-impact cukup dry run + observability.

4) Apa bedanya dry run dengan staging test?

Staging test menguji eksekusi nyata di lingkungan mirip production. Dry run hanya menampilkan rencana aksi. Keduanya saling melengkapi, bukan saling menggantikan.

FAQ Schema (JSON-LD, siap pakai)

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Apakah dry run saja sudah cukup untuk production?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Tidak selalu. Dry run membantu preview, tetapi perubahan berisiko tinggi tetap butuh approval gate, backup, dan rollback plan."
      }
    },
    {
      "@type": "Question",
      "name": "Kapan boleh pakai auto-approve (--yes)?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Gunakan saat pipeline sudah punya guardrail kuat: testing, environment restriction, dan audit log yang jelas. Hindari untuk eksekusi manual sensitif."
      }
    },
    {
      "@type": "Question",
      "name": "Bagaimana menjaga approval gate tetap efisien?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Klasifikasikan perubahan berdasarkan risiko. Terapkan manual approval hanya di high-impact change, sisanya cukup dry run dan logging yang baik."
      }
    },
    {
      "@type": "Question",
      "name": "Apa bedanya dry run dan staging test?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Dry run menampilkan rencana perubahan tanpa eksekusi, sedangkan staging test mengeksekusi sungguhan di lingkungan uji yang mirip production."
      }
    }
  ]
}

Penutup

Script yang aman itu bukan script yang “nggak pernah gagal”, tapi script yang terkontrol saat gagal dan jelas saat melakukan perubahan.

Mulai dari yang sederhana: jadikan default mode dry run, tambahkan approval gate di langkah kritikal, lalu rapikan backup + rollback. Tiga langkah ini udah cukup buat naik kelas dari “script jalan” jadi “operasi production yang bisa dipercaya”.

Komentar

Real-time

Memuat komentar...

Tulis Komentar

Email tidak akan ditampilkan

0/2000 karakter

Catatan: Komentar akan dimoderasi sebelum ditampilkan. Mohon bersikap sopan dan konstruktif.