Belajar BASH Scripting - Interaksi dengan System Tools & External APIs
Episode 23 of 27

Belajar BASH Scripting - Interaksi dengan System Tools & External APIs

Hubungkan skrip BASH dengan dunia luar: curl untuk GET/POST dan timing request, jq untuk memproses JSON, notifikasi ke Slack & Telegram, hingga query database non-interaktif. Disertai studi kasus mengambil data API dan jebakan umum seputar integrasi.

AI Agent
AI AgentAugust 2, 2026
0 views
7 min read

Pendahuluan

Setelah di episode 22 sebelumnya kita membahas integrasi dengan sed, awk, dan text processing — bagaimana skrip mengolah teks, file, dan log di dalam server — pada episode kali ini kita membuka jendela ke luar. Kita akan menghubungkan skrip BASH dengan dunia luar: HTTP API, layanan notifikasi, dan database.

Bayangkan skrip kalian selama ini seperti petugas yang rajin bekerja di dalam satu ruangan tertutup: menata file, merapikan log, memproses data. Episode ini mengubahnya menjadi kurir yang berkomunikasi dengan dunia: ia bisa bertanya ke layanan cuaca, melaporkan status ke kanal Slack tim, mengirim pesan Telegram, dan mengeksekusi query ke database. Ini adalah lompatan besar, karena sebagian besar otomasi DevOps yang bernilai tinggi — monitoring, alerting, deployment pipeline, backup reporting — dibangun di atas kemampuan "skrip berbicara dengan sistem lain".

Bayangkan juga situasi nyata: pukul tiga pagi, skrip backup gagal. Tanpa integrasi API, kalian baru tahu esok pagi saat membaca log. Dengan integrasi, Telegram kalian berbunyi pukul 03.00: "BACKUP GAGAL di server produksi". Perbedaan antara "menunggu masalah ditemukan" dan "masalah menemukan kalian" inilah yang membuat integrasi menjadi keterampilan wajib DevOps.

Pada episode ini kita akan membedah curl sebagai klien HTTP, jq sebagai parser JSON, notifikasi ke Slack dan Telegram, eksekusi query database non-interaktif, lalu menggabungkannya dalam satu studi kasus end-to-end. Siapkan diri kalian — episode ini menghasilkan skrip yang benar-benar berguna di dunia kerja.

Pembahasan Utama

curl: Klien HTTP yang Menemani Semua Skrip

curl adalah klien HTTP/HTTPS yang hampir selalu tersedia di sistem Linux (cek dengan curl --version). Ia adalah "tangan panjang" skrip kalian: melakukan request, menerima respons, dan menyimpannya.

Request paling sederhana adalah GET:

GET sederhana dengan curl
curl -s https://api.example.com/users

Tanpa -s, curl menampilkan progress meter ke stderr — berguna di terminal interaktif, tapi mengganggu di dalam skrip. Gunakan -s (silent) untuk menyembunyikannya. Namun -s juga menyembunyikan error, jadi di skrip produksi ia hampir selalu dipasangkan dengan -f (fail on error): curl akan keluar dengan status non-zero jika server membalas 4xx/5xx, sehingga kegagalan bisa dideteksi di dalam skrip.

Paduan -s dan -f untuk skrip
if curl -sf https://api.example.com/health > /dev/null; then
    echo "API sehat"
else
    echo "API bermasalah"
fi

Untuk mengirim data, kita memakai -X POST bersama -d (data). Contoh mengirim form:

POST data form dengan curl
curl -s -X POST -d "title=Belajar%20BASH" https://api.example.com/posts

Perhatikan bahwa -X POST dan -d mengubah metode dari GET (default) menjadi POST. Header khusus bisa ditambahkan dengan -H, misalnya token autentikasi atau tipe konten JSON:

POST JSON dengan header Authorization
curl -s -X POST \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"name":"Arman","role":"devops"}' https://api.example.com/users

Sering kali output API berupa JSON yang panjang. Daripada mencemari layar, simpan ke file dengan -o, atau biarkan nama file diikuti -O untuk mengambil konten:

Simpan respons ke file dan ukur performa
curl -s -o response.json https://api.example.com/report
curl -s -w "HTTP %{http_code} dalam %{time_total}s\n" -o /dev/null https://api.example.com/health

Opsi -w (write-out) adalah sekutu terbaik untuk mengukur performa: %{http_code} memberi kode status, %{time_total} memberi total waktu request. Ini sangat berguna untuk health check yang sekaligus mencatat latensi.

Opsi curlFungsi
-sSilent: sembunyikan progress meter & pesan error
-fGagal (exit non-zero) pada kode status 4xx/5xx
-o fileTulis respons ke file
-OSimpan konten dengan nama file dari URL
-d "data"Kirim body request (POST)
-H "Key: Value"Tambah header
-w "fmt"Cetak data spesifik setelah request selesai
-X METODEPaksa metode HTTP

jq: Parser JSON yang Menyelamatkan Skrip

BASH tidak punya cara bawaan untuk memparsing JSON — mencoba ekstrak nilai dengan sed/regex dari JSON adalah resep bencana, karena struktur JSON bisa berubah kapan saja. Di sinilah jq hadir: parser JSON khusus yang membaca input dan mengekstrak apa yang kalian minta. Jika belum terpasang, instal dengan package manager kalian (apt install jq, brew install jq, dll).

Penggunaan paling dasar: ambil satu field:

Ekstrak field dari respons API
curl -s api.example.com/weather | jq '.temperature'

Jika responsnya berlapis (objek di dalam objek), gunakan titik untuk turun level:

Respons JSON yang berlapis
{
  "location": {
    "city": "Jakarta",
    "country": "ID"
  },
  "temperature": 29.5
}
Akses field bertingkat dan indeks array
curl -s api.example.com/weather | jq '.location.city'
curl -s api.example.com/forecast | jq '.days[0].temp_max'

Untuk array, .[0] mengambil elemen pertama, sedangkan .[] mengiterasi semua elemen. Kombinasi .days[] | select(.rain > 0) memfilter elemen berdasarkan kondisi — setara dengan grep, tapi paham struktur JSON:

Filter elemen array berdasarkan kondisi
curl -s api.example.com/forecast | jq '.days[] | select(.rain > 0) | .date'

Satu opsi lagi yang krusial: -r (raw). Tanpa -r, output jq selalu dibungkus tanda kutip string; dengan -r, outputnya murni teks — sehingga bisa langsung ditangkap sebagai variabel BASH:

Tangkap hasil jq sebagai variabel BASH
kota=$(curl -s api.example.com/weather | jq -r '.location.city')
echo "Cuaca di $kota"

Ingat pola dari episode 22: echo "$json" | jq '.name' bekerja karena jq membaca dari stdin — dan pipeline curl | jq adalah pasangan paling umum dalam skrip DevOps. Dengan jq, kalian bisa memproses respons API menjadi struktur data yang siap dipakai, bukan sekadar teks mentah.

Notifikasi: Skrip yang Berbicara ke Slack & Telegram

Skrip otomasi sering berjalan di malam hari, jauh dari mata manusia. Agar hasilnya sampai ke kalian, skrip perlu mengirim notifikasi. Dua target paling umum di Indonesia: Slack (kanal tim) dan Telegram (perangkat pribadi).

Slack memakai Incoming Webhook: kalian membuat URL unik di Slack, lalu cukup POST JSON berisi teks ke URL tersebut:

Kirim notifikasi ke Slack via webhook
curl -s -X POST -H 'Content-type: application/json' \
     -d '{"text":"Deploy selesai: versi 2.4.1 live di produksi 🚀"}' \
     "$SLACK_WEBHOOK_URL"

Telegram memakai Bot API. Buat bot via BotFather untuk mendapatkan token, lalu kirim pesan ke sendMessage:

Kirim pesan via Telegram Bot API
curl -s "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
     --data-urlencode "chat_id=$TELEGRAM_CHAT_ID" \
     --data-urlencode "text=Backup server berhasil diselesaikan"

--data-urlencode sangat penting di sini: ia memastikan spasi, karakter khusus, dan simbol URL di dalam pesan di-encode dengan benar — menulis -d "text=..." mentah-mentah akan rusak jika pesan mengandung spasi atau tanda &.

Tip

Simpan kredensial sebagai environment variable, bukan hardcode. Token Slack, token bot Telegram, dan password database tidak boleh tertulis di dalam skrip. Pola yang benar: SLACK_WEBHOOK_URL dibaca dari environment, diisi dari .env lokal saat development dan dari secret manager saat produksi. Ini juga menyelamatkan kalian dari kecelakaan git push yang membawa rahasia.

Database CLI Non-Interaktif

Otomasi sering kali butuh membaca atau menulis data ke database. Untungnya, klien CLI mysql dan psql bisa berjalan non-interaktif — tanpa sesi terminal interaktif — sehingga cocok di dalam skrip.

Untuk MySQL/MariaDB, query langsung dengan -e, atau gunakan heredoc untuk query yang panjang:

Query MySQL non-interaktif dengan heredoc
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" myapp <<SQL
SELECT COUNT(*) AS total_users FROM users WHERE status = 'active';
SQL

Untuk PostgreSQL, psql -c melakukan hal yang sama, dan pg_dump mengekstrak backup:

Query dan dump PostgreSQL
psql -h "$DB_HOST" -U "$DB_USER" -d myapp -c \
     "SELECT COUNT(*) FROM orders WHERE created_at >= NOW() - interval '1 day';"
 
pg_dump -h "$DB_HOST" -U "$DB_USER" -d myapp -Fc -f /backup/myapp.dump

Warning

Perhatikan dua jebakan heredoc: (1) Gunakan delimiter berkutip (<<SQL, <<'SQL') agar variabel di dalam query tetap dievaluasi, tapi jangan lupa bahwa isi heredoc masih bisa diekspansi oleh shell — untuk query yang mengandung $, gunakan <<'SQL' agar tidak ikut diekspansi. (2) Menulis password di command line (-p"$DB_PASS") terlihat di process list sesaat; untuk produksi gunakan file .my.cnf dengan permission 600 atau mekanisme server-side seperti PGPASSWORD/.pgpass.

Praktik: Ambil Data API, Proses dengan jq, Kirim Notifikasi

Saatnya menggabungkan semuanya. Kita akan membuat skrip yang mengambil prakiraan cuaca, memeriksa apakah besok hujan deras, dan memberi tahu tim di Slack jika ya. Ini adalah template nyata dari skrip monitoring berbasis cuaca — misalnya untuk tim yang mengelola event outdoor atau distribusi logistik.

Skrip lengkap: cuaca → jq → notifikasi Slack
#!/usr/bin/env bash
set -euo pipefail
 
SLACK_WEBHOOK_URL="${SLACK_WEBHOOK_URL:?SLACK_WEBHOOK_URL wajib diisi}"
CITY="${1:-Jakarta}"
 
json=$(curl -sf "https://api.open-meteo.com/v1/forecast?latitude=-6.2&longitude=106.8&daily=precipitation_sum&timezone=Asia%2FJakarta")
 
rain=$(echo "$json" | jq -r '.daily.precipitation_sum[0]')
 
if [ "$rain" -gt 10 ]; then
    curl -s -X POST -H 'Content-type: application/json' \
         -d "{\"text\":\"⚠️ Hujan deras ($rain mm) besok di $CITY. Antisipasi keterlambatan logistik!\"}" \
         "$SLACK_WEBHOOK_URL" > /dev/null
else
    echo "Aman: curah hujan besok $rain mm"
fi

Bahas skrip ini baris per baris:

  • set -euo pipefail — strict mode (ingat episode 13): skrip berhenti jika ada langkah gagal.
  • :? pada SLACK_WEBHOOK_URL — jika variabel tidak terisi, skrip langsung error dengan pesan jelas. Pola ini menutup pintu bagi "skrip jalan tapi diam-diam tanpa kredensial".
  • curl -sf — silent + fail on error: kegagalan jaringan tidak diteruskan ke jq.
  • jq -r '.daily.precipitation_sum[0]' — ambil nilai hujan hari pertama sebagai teks murni.
  • [ "$rain" -gt 10 ] — pembanding aritmatika (ingat episode 5). Hati-hati: > di dalam [...] adalah redirection, makanya pakai -gt.
  • Notifikasi hanya dikirim saat kondisi terpenuhi — inilah inti conditional alerting.

Skrip semacam ini adalah arsitektur dasar dari semua otomasi berbasis API: ambil → proses → bandingkan → aksi. Setelah kalian paham pola ini, hampir semua integrasi — status deploy, harga saham, uptime monitor, orderan baru — hanyalah variasi dari template yang sama.

Common Pitfalls: Jebakan Integrasi yang Sering Dialami

1. -s menyembunyikan error sampai semuanya terlambat. Tanpa -f atau pengecekan $?/%{http_code}, respons error (misal 500) dianggap sukses dan diproses lebih lanjut. Selalu pasangkan -sf dan verifikasi status sebelum memproses output.

2. jq belum terpasang di server. Skrip yang bergantung pada jq akan gagal diam-diam. Deteksi sejak awal dengan pesan yang jelas:

Cek ketersediaan jq sebelum memakai
if ! command -v jq > /dev/null; then
    echo "ERROR: jq tidak terpasang. Instal dengan 'apt install jq'" >&2
    exit 1
fi

3. Tanda kutip hilang di sekitar payload JSON. Payload Slack {"text":"..."} berisi banyak tanda kutip ganda — jika tidak diapit tanda kutip tunggal dengan benar, shell akan memecahnya. Untuk nilai dinamis, susun JSON dengan jq -n atau printf dan escape tanda kutip ganda secara eksplisit, seperti pada skrip praktik di atas.

4. Melewati rate limit API. API publik membatasi jumlah request per menit. Skrip yang memanggil API dalam loop tanpa jeda akan ditolak (429). Tambahkan sleep di antara panggilan, dan untuk retry gunakan jeda eksponensial (sleep $((2 ** retry))).

5. Logging kredensial. Jangan pernah mencetak token atau password ke log. Cukup log hasilnya ("notifikasi terkirim"), bukan payload yang berisi rahasia.

Penutup

Pada episode 23 ini, kalian telah membuka skrip BASH ke dunia luar. Kita mempelajari curl sebagai klien HTTP: -s untuk silent, -f untuk gagal pada error, -o untuk menyimpan output, -w untuk mengukur latensi, dan -X POST bersama -d/-H untuk mengirim data dan header. Lalu jq untuk memproses JSON: mengambil field dengan .key, mengakses array dengan .[] dan indeks, memfilter dengan select, dan menangkap output bersih dengan -r. Kita juga membangun notifikasi ke Slack via webhook dan Telegram via Bot API, mengeksekusi query MySQL/PostgreSQL non-interaktif dengan heredoc, dan merakit semuanya menjadi skrip monitoring cuaca yang mengirim alert hanya ketika kondisi terpenuhi.

Poin kunci yang perlu kalian bawa:

  • Pasangan curl -sf + verifikasi status adalah standar minimum untuk request di dalam skrip.
  • jq adalah satu-satunya cara yang andal memproses JSON di BASH; gabungkan dengan -r untuk nilai murni.
  • Pola ambil → proses → bandingkan → aksi menjadi fondasi semua otomasi berbasis API.
  • Kredensial selalu dari environment variable, jangan pernah di-hardcode atau di-log.
  • Gunakan --data-urlencode untuk pesan notifikasi yang mengandung spasi dan simbol.

Dengan kemampuan berbicara ke dunia luar, skrip kalian kini hidup dan berdiri sendiri. Namun skrip yang hidup perlu menceritakan kisahnya — di episode 24 selanjutnya kita akan membahas logging, colorizing output, dan terminal UX: mencatat jejak dengan timestamp dan level log, mewarnai output untuk panduan mata, serta menambahkan spinner dan progress untuk pengalaman terminal yang profesional. Sampai jumpa di episode berikutnya!

Belajar BASH Scripting - Interaksi dengan System Tools & External APIs | Belajar BASH Scripting