JQ untuk Shell Script Linux: Cara Parse JSON API dengan Aman di Automation Production

Last updated on


Target keyword: jq shell script linux parse json api automation

Search intent: Problem-solving / Best-practice

Monthly keyword cluster: linux shell scripting, bash scripting linux, automasi tugas linux

Weekly intent rotation: Troubleshooting + implementasi praktis

Kalau kamu sering bikin automasi berbasis shell script, cepat atau lambat kamu bakal ketemu data JSON dari API: status deployment, hasil health check, daftar job, sampai token metadata. Tantangannya bukan cuma “gimana ngambil nilainya”, tapi gimana ngambilnya dengan aman saat data tidak konsisten, API timeout, atau respons error tapi HTTP status-nya tetap 200.

Di sinilah jq jadi senjata wajib. Dengan jq, kamu bisa parse JSON secara konsisten, validasi struktur data, kasih fallback value, dan bikin alur script lebih tahan banting di production.

Artikel ini fokus ke use case nyata: integrasi API di shell script Linux yang dipakai untuk cron/systemd timer atau pipeline harian. Targetnya sederhana: script kamu tetap kebaca, gampang di-debug, dan minim false success.

Kenapa parsing JSON di shell script sering bikin masalah?

Masalah paling umum biasanya ini:

  • Parsing pakai grep/cut/sed untuk JSON (rapuh banget kalau format berubah sedikit).
  • Script tidak bedain network error, HTTP error, dan business logic error.
  • Nilai kosong/null tidak ditangani, akhirnya command lanjut dengan data invalid.
  • Logging kurang jelas, jadi pas error tim bingung masalahnya di mana.

Kalau script itu menyentuh workflow penting (backup, deployment, sinkron data), satu parsing error kecil bisa jadi incident besar.

Prasyarat

  • Linux server / VM dengan Bash.
  • curl untuk request API.
  • jq untuk parse JSON.

Instal cepat:

# Ubuntu/Debian
sudo apt-get update && sudo apt-get install -y jq curl

# Verifikasi
jq --version
curl --version | head -n1

Pola dasar: curl + jq yang aman

Banyak script gagal karena langsung:

curl -s https://api.example.com/jobs | jq -r '.data[0].id'

Ini “jalan” saat semua normal, tapi rapuh. Versi yang lebih aman:

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

API_URL="https://api.example.com/jobs"
TMP_JSON="$(mktemp)"
trap 'rm -f "$TMP_JSON"' EXIT

HTTP_CODE=$(curl -sS --connect-timeout 5 --max-time 20 \
  -H "Accept: application/json" \
  -o "$TMP_JSON" \
  -w "%{http_code}" \
  "$API_URL")

if [[ "$HTTP_CODE" -lt 200 || "$HTTP_CODE" -ge 300 ]]; then
  echo "[ERROR] HTTP $HTTP_CODE from $API_URL"
  echo "[DEBUG] body: $(head -c 300 "$TMP_JSON")"
  exit 1
fi

if ! jq empty "$TMP_JSON" >/dev/null 2>&1; then
  echo "[ERROR] Response bukan JSON valid"
  exit 1
fi

JOB_ID=$(jq -r '.data[0].id // empty' "$TMP_JSON")
if [[ -z "$JOB_ID" ]]; then
  echo "[ERROR] data[0].id kosong / tidak ada"
  exit 1
fi

echo "[INFO] JOB_ID=$JOB_ID"

Poin penting dari pola ini:

  1. Pisahkan HTTP code dan body biar validasi jelas.
  2. Cek JSON valid dulu dengan jq empty.
  3. Pakai fallback // empty supaya null tidak diam-diam dianggap sukses.
  4. Gunakan set -Eeuo pipefail agar error tidak ketelan.

Teknik jq yang paling kepakai di automation

1) Ambil nilai dengan fallback aman

jq -r '.metadata.region // "unknown"' response.json

Kalau field tidak ada/null, tetap dapat nilai default.

2) Validasi field wajib sebelum lanjut

jq -e '.status == "ok" and (.data | type == "array")' response.json >/dev/null

-e bikin exit code non-zero kalau ekspresi false. Cocok untuk guard clause di script.

3) Filter item berdasarkan kondisi

jq -r '.jobs[] | select(.state=="failed") | .id' response.json

Ini enak buat incident triage otomatis.

4) Bentuk output ringkas untuk logging

jq -r '{request_id, status, count: (.data|length)}' response.json

Log jadi lebih padat dan relevan.

5) Hindari error saat array kosong

jq -r '.data[0]?.id // empty' response.json

Operator ? mencegah crash saat elemen tidak ada.

Contoh use case nyata: health check API + retry sederhana

Misal kamu mau script health check untuk endpoint internal. Tujuan kita:

  • Retry kalau timeout/intermiten.
  • Gagal kalau status app bukan healthy.
  • Log ringkas untuk observability.
#!/usr/bin/env bash
set -Eeuo pipefail

URL="https://internal-api.example.com/health"
MAX_RETRY=3
SLEEP_SEC=2

log() {
  echo "[$(date '+%F %T')] $*"
}

attempt=1
while (( attempt <= MAX_RETRY )); do
  BODY_FILE="$(mktemp)"
  trap 'rm -f "$BODY_FILE"' RETURN

  HTTP_CODE=$(curl -sS --connect-timeout 3 --max-time 10 \
    -o "$BODY_FILE" -w "%{http_code}" "$URL" || echo "000")

  if [[ "$HTTP_CODE" == "000" ]]; then
    log "WARN network error (attempt $attempt/$MAX_RETRY)"
  elif [[ "$HTTP_CODE" -ge 200 && "$HTTP_CODE" -lt 300 ]]; then
    if jq -e '.status == "healthy"' "$BODY_FILE" >/dev/null 2>&1; then
      VERSION=$(jq -r '.version // "unknown"' "$BODY_FILE")
      LATENCY=$(jq -r '.latency_ms // -1' "$BODY_FILE")
      log "OK status=healthy version=$VERSION latency_ms=$LATENCY"
      exit 0
    else
      log "WARN app unhealthy (attempt $attempt/$MAX_RETRY)"
      log "DEBUG $(jq -c '{status, message, code}' "$BODY_FILE" 2>/dev/null || head -c 200 "$BODY_FILE")"
    fi
  else
    log "WARN http=$HTTP_CODE (attempt $attempt/$MAX_RETRY)"
  fi

  (( attempt++ ))
  sleep "$SLEEP_SEC"
done

log "ERROR health check failed after $MAX_RETRY attempts"
exit 1

Script ini udah cukup aman untuk dipasang di cron/systemd timer karena:

  • Tidak menganggap respons 200 sebagai pasti sukses.
  • Ada retry terkontrol.
  • Ada log yang bisa langsung dipakai investigasi.

Troubleshooting umum saat pakai jq

Masalah 1: jq: command not found

Penyebab: package jq belum terpasang di host runtime (sering kejadian di container slim).

Solusi:

  • Tambahkan jq di image build/deploy.
  • Buat preflight check di awal script.
command -v jq >/dev/null || { echo "jq belum terpasang"; exit 1; }

Masalah 2: Output kosong padahal field ada

Penyebab: path JSON salah atau struktur respons berubah.

Solusi: inspect struktur dulu.

jq '.' response.json | less
jq -r 'paths | join(".")' response.json | head -n 80

Masalah 3: Script tetap lanjut walau ekspresi jq false

Penyebab: tidak pakai -e atau tidak cek exit code.

Solusi:

if ! jq -e '.status=="ok"' response.json >/dev/null; then
  echo "status bukan ok"
  exit 1
fi

Masalah 4: JSON invalid dari upstream

Penyebab: API gateway/error page HTML dikirim sebagai body.

Solusi: selalu validasi JSON sebelum parse field.

jq empty response.json >/dev/null 2>&1 || exit 1

Checklist implementasi production

  • Selalu pisahkan HTTP status dan body respons.
  • Gunakan jq empty untuk cek validitas JSON.
  • Pakai jq -e untuk validasi kondisi wajib.
  • Terapkan fallback (// empty / default value) untuk field opsional.
  • Tambahkan retry + timeout yang realistis.
  • Pastikan log memuat context minimum: endpoint, status, attempt, request id (jika ada).
  • Uji skenario error: timeout, 500, payload null, payload schema berubah.

Biar implementasi makin matang, kamu bisa lanjut ke artikel terkait ini:

FAQ (Schema-ready)

Format tanya-jawab di bawah sudah siap dipetakan ke FAQPage JSON-LD.

1) Kapan sebaiknya pakai jq dibanding grep/sed untuk JSON?

Begitu input kamu berupa JSON dari API, langsung pakai jq. grep/sed mungkin terlihat cepat di awal, tapi rentan rusak saat struktur JSON berubah dan sulit dijaga untuk production.

2) Apakah jq cukup aman untuk script production?

Aman, selama dipakai dengan pola yang benar: validasi JSON (jq empty), validasi kondisi (jq -e), fallback value, plus timeout/retry di layer request (curl).

3) Gimana cara bikin script gagal cepat saat data penting hilang?

Gunakan guard clause setelah parsing:

ID=$(jq -r '.data.id // empty' resp.json)
[[ -n "$ID" ]] || { echo "ID wajib tidak ada"; exit 1; }

4) Kalau API kadang lambat, apa cukup retry saja?

Jangan retry buta. Kombinasikan connect-timeout, max-time, retry terbatas, dan logging attempt. Kalau tetap gagal, exit non-zero supaya monitoring bisa nangkap.

Penutup

jq bukan cuma tools “biar parsing lebih rapi”, tapi pondasi penting buat automation shell script yang tahan gangguan. Dengan pola validasi JSON, guard clause, retry terkontrol, dan logging yang jelas, kamu bisa turunin risiko false success secara signifikan.

Kalau kamu lagi audit script lama, mulai dari endpoint paling kritis dulu: ganti parsing rapuh ke jq, tambah validation gate, lalu uji skenario gagal. Perubahan kecil ini biasanya langsung kerasa dampaknya di stabilitas production.

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.