Kodeloka
  1. Kodeloka
  2. Kelas Linux & Shell
  3. Materi

3 · Shell · Modul 5 dari 8

Pipe, Redirection & Perkakas Teks

Merangkai perintah kecil menjadi analisis yang kuat — keterampilan yang paling sering terpakai saat menelusuri masalah produksi.

Redirection

perintah > berkas         # tulis (timpa) stdout
perintah >> berkas        # tambahkan
perintah 2> galat.log     # stderr saja
perintah > keluar.log 2>&1   # keduanya ke satu berkas
perintah &> semua.log     # ringkasnya (bash)
perintah < masukan.txt    # baca dari berkas
perintah 2>/dev/null      # buang pesan error
⚠️ Urutan 2>&1 itu penting
# ✅ BENAR — stdout diarahkan ke berkas, lalu stderr mengikuti stdout
perintah > berkas 2>&1

# ❌ SALAH — stderr menyalin tujuan stdout SAAT ITU (masih terminal),
#    baru kemudian stdout dialihkan ke berkas
perintah 2>&1 > berkas

Kesalahan ini membuat pesan error tetap muncul di layar dan tidak tercatat — biasanya baru ketahuan saat Anda benar-benar membutuhkannya.

Pipe

ps aux | grep nginx | grep -v grep
cat akses.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

# Menyalurkan stderr juga
perintah |& less

# tee: simpan sekaligus teruskan
perintah | tee keluaran.log | grep ERROR

grep

grep -i "error" app.log            # abaikan besar-kecil huruf
grep -r "TODO" src/                # rekursif
grep -n "gagal" app.log            # dengan nomor baris
grep -v "debug" app.log            # KECUALI yang cocok
grep -c "error" app.log            # hitung saja
grep -A3 -B3 "panic" app.log       # 3 baris sebelum & sesudah
grep -E "error|fatal|panic" app.log
grep -o "user_id=[0-9]*" app.log   # hanya bagian yang cocok
grep -l "koneksi" *.log            # nama berkasnya saja
📌 -A dan -B mengubah cara menelusuri log

Menemukan baris error saja sering tidak cukup — Anda butuh konteks di sekitarnya untuk tahu apa yang terjadi sebelumnya. grep -B5 -A10 "panic" memberi gambaran jauh lebih utuh daripada sekadar barisnya.

awk

# Kolom ke-1 dan ke-7 dari log akses
awk '{print $1, $7}' akses.log

# Baris dengan kode status 500
awk '$9 == 500' akses.log

# Jumlahkan kolom ukuran respons
awk '{jumlah += $10} END {print jumlah/1024/1024 " MB"}' akses.log

# Hitung per kode status
awk '{hitung[$9]++} END {for (k in hitung) print k, hitung[k]}' akses.log

# Pemisah kolom kustom
awk -F: '{print $1}' /etc/passwd
awk -F',' '{print $2}' data.csv

sed

sed 's/lama/baru/' berkas          # ganti kemunculan PERTAMA tiap baris
sed 's/lama/baru/g' berkas         # semua kemunculan
sed -i.bak 's/lama/baru/g' berkas  # ubah langsung, simpan cadangan .bak
sed -n '10,20p' berkas             # cetak baris 10-20
sed '/^#/d' konfigurasi            # hapus baris komentar
sed '/^$/d' berkas                 # hapus baris kosong
🚫 sed -i tanpa cadangan pada berkas produksi

Opsi -i mengubah berkas di tempat, dan bila polanya keliru, isi aslinya sudah hilang. Selalu pakai -i.bak agar salinan tersimpan, atau jalankan tanpa -i lebih dulu untuk melihat hasilnya di layar sebelum menerapkan.

jq untuk JSON

curl -s api/pesanan | jq '.'
curl -s api/pesanan | jq '.data[] | {id, total}'
curl -s api/pesanan | jq '.data[] | select(.total > 100000)'
curl -s api/pesanan | jq -r '.data[].id'        # -r: tanpa tanda kutip
kubectl get pods -o json | jq -r '.items[].metadata.name'

# Menyaring log JSON terstruktur
tail -f app.log | jq -c 'select(.level=="error") | {waktu, msg, trace_id}'
💡 Inilah alasan log terstruktur sepadan

Ketika log berupa JSON, jq mengubahnya menjadi sesuatu yang bisa dikueri: saring level, ambil field tertentu, hitung per kategori. Log berupa kalimat bebas hanya bisa dihadapi dengan regex yang rapuh. Perbedaannya sangat terasa saat menelusuri insiden.

Rangkaian yang Sering Dipakai

# 10 alamat IP dengan permintaan terbanyak
awk '{print $1}' akses.log | sort | uniq -c | sort -rn | head -10

# Sebaran kode status
awk '{print $9}' akses.log | sort | uniq -c | sort -rn

# Error per jam
grep ERROR app.log | awk '{print substr($1,1,13)}' | uniq -c

# 20 berkas terbesar di bawah direktori ini
find . -type f -printf '%s %p\n' | sort -rn | head -20 | \
  awk '{printf "%.1f MB  %s\n", $1/1024/1024, $2}'

# Proses yang mendengarkan port beserta pemiliknya
ss -tulpn | awk 'NR>1 {print $5, $7}'