"Terminal bukan alat yang menakutkan. Itu adalah alat yang memberimu kendali penuh atas komputer — dan server."
Tentang E-Book Ini
Hampir semua server di dunia menjalankan Linux. Docker container pakai Linux. VPS yang kamu deploy ke production pakai Linux. CI/CD pipeline berjalan di Linux. Tapi banyak developer, terutama yang terbiasa dengan Windows atau Mac dengan GUI, merasa asing ketika harus berinteraksi dengan server melalui terminal.
E-book ini mengubah itu. Kita mulai dari dasar: navigasi filesystem, membaca dan menulis file, memahami permissions, lalu ke hal-hal yang dipakai sehari-hari: SSH ke server remote, mengelola proses, mencari teks di log, sampai menulis script sederhana untuk otomasi.
Tidak ada yang perlu diinstall — semua yang ada di e-book ini bisa langsung dicoba di Terminal (Mac/Linux) atau WSL (Windows).
Prasyarat: Tidak ada. Tapi disarankan sudah membaca e-book #00 (Cara Kerja HTTP) untuk konteks mengapa kamu perlu ini.
Daftar Isi
- Kenapa Developer Harus Bisa Terminal?
- Navigasi Filesystem
- Membaca, Menulis & Mencari File
- Permissions & Ownership
- Proses & Background Jobs
- SSH: Masuk ke Server Remote
- Package Management & Setup Environment
- Tools Sehari-hari untuk Backend Developer
- Shell Script & Otomasi
Bab 1: Kenapa Developer Harus Bisa Terminal?
GUI vs CLI: Bukan Pilihan, Tapi Pelengkap
GUI (Graphical User Interface) bagus untuk eksplorasi dan produktivitas sehari-hari. Tapi ada hal-hal yang CLI (Command Line Interface) lakukan jauh lebih baik:
Otomasi — kamu bisa menyimpan serangkaian perintah dalam sebuah script dan menjalankannya kapanpun, berkali-kali, tanpa error ketik seperti kalau dilakukan manual. Deploy dengan satu perintah, bukan 12 langkah klik.
Remote access — server production tidak punya layar dan mouse. Terminal adalah satu-satunya cara mengelola server remote via SSH.
Konsistensi — rm -rf node_modules && npm install adalah instruksi yang sama persis di mana saja. "Klik kanan di panel sebelah kiri, pilih properties..." sudah berbeda di versi yang berbeda.
Kecepatan — setelah terbiasa, perintah terminal jauh lebih cepat daripada navigasi menu. Rename 1000 file dalam satu perintah vs klik satu per satu.
Dokumentasi teknis — hampir semua README, tutorial, dan dokumentasi teknis ditulis dalam bentuk perintah terminal. Tidak bisa terminal = tidak bisa mengikuti banyak tutorial.
Membuka Terminal
Mac: Cmd + Space → ketik "Terminal" → Enter. Atau pasang iTerm2 (gratis, lebih powerful dengan split pane, search, dll).
Linux (Ubuntu/Debian): Ctrl + Alt + T
Windows: Install WSL (Windows Subsystem for Linux) — jalankan Ubuntu langsung di Windows tanpa VM. Buka Microsoft Store, cari "Ubuntu 22.04", install. Buka "Ubuntu" dari Start Menu, ikuti setup awal.
Shell: Bash vs Zsh
Shell adalah program yang membaca perintahmu dan menjalankannya. Yang paling umum:
Bash (Bourne Again Shell) — default di hampir semua distro Linux. Pilihan aman untuk scripting karena tersedia di mana-mana.
Zsh (Z Shell) — default di Mac sejak macOS Catalina. Lebih nyaman dipakai interaktif: autocomplete lebih pintar, plugin ekosistem yang kaya (Oh My Zsh).
Untuk e-book ini, semua perintah bekerja di keduanya. Config file:
- Bash:
~/.bashrc(Linux) atau~/.bash_profile(Mac) - Zsh:
~/.zshrc
Anatomi Command
perintah [opsi] [argumen]
│ │ │
│ │ └─ Target (file, direktori, URL, dll)
│ └─ Modifier yang mengubah perilaku (dimulai - atau --)
└─ Program yang dijalankanls -la /home/rinaldy
│ │ └─ argumen: direktori
│ └─ opsi: -l (long format) dan -a (semua termasuk tersembunyi)
└─ perintah: list directoryMinta bantuan:
man ls # manual page lengkap (navigasi: space/b, cari: /kata, keluar: q)
ls --help # ringkasan cepatBab 2: Navigasi Filesystem
Struktur Direktori Linux
Linux menggunakan pohon direktori tunggal yang berakar di / (root):
/
├── home/ ← direktori home semua user non-root
│ └── rinaldy/ ← home directory kamu (~)
│ ├── .bashrc ← config bash (file tersembunyi = diawali .)
│ ├── .ssh/ ← SSH keys dan config
│ └── projects/
├── etc/ ← file konfigurasi sistem (nginx.conf, hosts, dll)
├── var/ ← data yang berubah: log, database, cache
│ ├── log/ ← log sistem dan aplikasi
│ └── www/ ← file web server (konvensi umum)
├── usr/
│ ├── bin/ ← executable program yang diinstall
│ └── local/ ← program yang diinstall secara lokal
├── opt/ ← software third-party (Node.js, dsb)
├── tmp/ ← file sementara (dihapus saat reboot)
└── root/ ← home directory user root (superuser)
Tilde ~ adalah shortcut untuk home directory kamu — /home/rinaldy (Linux) atau /Users/rinaldy (Mac).
Perintah Navigasi
pwd # Print Working Directory — kamu sedang di mana?
# /home/rinaldy/projects
ls # list isi direktori saat ini
ls /etc # list direktori lain
ls -l # long format: permission, owner, size, tanggal
ls -a # tampilkan file tersembunyi (diawali .)
ls -la # kombinasi: long + all
ls -lh # -h: ukuran human-readable (KB, MB, GB)
ls -lt # sort by modification time (terbaru dulu)
ls -lS # sort by size (terbesar dulu)
cd /home/rinaldy # pindah ke absolute path
cd projects # pindah ke relative path (subdirektori)
cd .. # naik satu level
cd ../.. # naik dua level
cd ~ # langsung ke home directory
cd - # kembali ke direktori sebelumnya (toggle)Membuat & Mengelola Direktori dan File
mkdir myproject # buat direktori
mkdir -p api/src/controllers # buat nested direktori sekaligus
cp file.txt backup.txt # copy file
cp -r src/ dst/ # copy direktori (rekursif)
cp -rp src/ dst/ # copy dengan preserve permissions + timestamps
mv old-name.txt new-name.txt # rename file
mv file.txt ~/Documents/ # pindahkan ke direktori lain
mv *.log /var/log/archive/ # pindahkan semua .log ke arsip
rm file.txt # hapus file
rm -r myproject/ # hapus direktori rekursif
rm -rf myproject/ # hapus paksa tanpa konfirmasi (hati-hati!)
rm -i file.txt # -i: minta konfirmasi sebelum hapus
touch newfile.txt # buat file kosong, atau update timestamp file yang ada
# Buat symbolic link (shortcut)
ln -s /var/log/nginx/access.log ~/nginx-access.logPeringatan:
rmtidak ada Recycle Bin. File yang dihapus langsung hilang permanen. Selalu verifikasi path sebelumrm -rf.
Absolute vs Relative Path
# Absolute — mulai dari root /, berlaku dari mana saja
cd /home/rinaldy/projects/myapi
cat /etc/nginx/nginx.conf
# Relative — relatif dari posisi saat ini
# Jika kamu di /home/rinaldy:
cd projects/myapi # = /home/rinaldy/projects/myapi
cd ../Documents # = /home/rinaldy/Documents
cat ../../etc/hosts # = /etc/hosts (naik dua level dulu)Bab 3: Membaca, Menulis & Mencari File
Membaca File
cat file.txt # tampilkan semua isi file sekaligus
cat -n file.txt # dengan nomor baris
less file.txt # tampilkan per halaman (Space: next, b: back, q: quit, /: cari)
more file.txt # seperti less tapi lebih sederhana
head file.txt # 10 baris pertama
head -n 20 file.txt # 20 baris pertama
tail file.txt # 10 baris terakhir
tail -n 50 app.log # 50 baris terakhir
tail -f app.log # follow: tampilkan baris baru real-time (Ctrl+C untuk stop)
tail -F app.log # follow: reconnect jika file dirotasi (lebih robust)tail -f adalah perintah yang paling sering dipakai developer saat monitoring log aplikasi yang sedang berjalan.
Menulis File
echo "Hello World" # print ke terminal
echo "Hello" > file.txt # tulis ke file (timpa jika sudah ada)
echo "Baris baru" >> file.txt # append ke akhir file
# Heredoc: tulis multi-line ke file
cat > config.json << 'EOF'
{
"host": "localhost",
"port": 5432,
"database": "myapp"
}
EOFText Editor di Terminal
nano — paling mudah untuk pemula:
nano server.js
# Shortcut (^ = Ctrl):
# ^O → Write Out (save)
# ^X → Exit
# ^K → Cut baris
# ^U → Uncut (paste)
# ^W → Where Is (cari)
# ^G → Get Helpvim — kurva belajar curam tapi sangat powerful setelah terbiasa:
vim server.js
# Mode:
# Normal (default) — untuk navigasi dan perintah
# Insert — untuk mengetik teks (tekan i)
# Visual — untuk seleksi teks (tekan v)
# Perintah Normal mode:
# i → masuk Insert mode sebelum cursor
# a → masuk Insert mode setelah cursor
# Esc → kembali ke Normal mode
# :w → save
# :q → quit
# :wq → save + quit
# :q! → quit paksa tanpa save
# /kata → cari ke depan
# n → next search result
# dd → hapus baris
# yy → copy (yank) baris
# p → paste
# u → undo
# Ctrl+r → redo
# gg → pergi ke baris pertama
# G → pergi ke baris terakhir
# :42 → pergi ke baris 42Pipe: Sambungkan Perintah
Pipe | mengambil output perintah pertama sebagai input perintah kedua:
cat app.log | grep "ERROR" # filter baris error
ls -la | sort -k5 -n # list file, sort by size (kolom 5)
cat access.log | wc -l # hitung jumlah baris log
ps aux | grep node | grep -v grep # cari proses Node.js
cat big-file.txt | head -100 | tail -10 # baris 91-100Mencari File dan Konten
# find: cari file berdasarkan nama/tipe/ukuran/waktu
find . -name "*.js" # semua file .js dari sini
find . -name "*.js" -not -path "*/node_modules/*" # exclude node_modules
find /var/log -name "*.log" -mtime -1 # log yang dimodifikasi dalam 1 hari terakhir
find . -type d -name "dist" # hanya cari direktori bernama dist
find . -size +10M # file lebih besar dari 10MB
find . -empty # file kosong
find . -name "*.tmp" -delete # cari dan hapus sekaligus
# grep: cari teks di dalam file
grep "ERROR" app.log # baris yang mengandung "ERROR"
grep -i "error" app.log # case insensitive
grep -n "TODO" src/server.js # tampilkan nomor baris
grep -r "db.query" ./src # rekursif di semua file dalam ./src
grep -v "DEBUG" app.log # tampilkan baris yang TIDAK mengandung DEBUG
grep -c "404" access.log # hitung jumlah match
grep -l "process.env" ./src/**/*.js # hanya tampilkan nama file yang match
grep -A 3 -B 2 "FATAL" app.log # 2 baris sebelum dan 3 baris setelah match
# Kombinasi powerful
grep "ERROR" app.log | grep "2026-06-29" | wc -l # jumlah error hari ini
grep -r "TODO\|FIXME\|HACK" ./src --include="*.js" # cari technical debtBab 4: Permissions & Ownership
Membaca Permission
Output ls -l:
-rwxr-xr-- 1 rinaldy staff 4096 Jun 29 10:00 server.js
│└──┴──┴── │ │
│ │ │ └─ Others (semua user lain): r-- = read only
│ │ └──── Group (anggota group staff): r-x = read + execute
│ └─────── Owner (rinaldy): rwx = read + write + execute
└────────── File type: - = file, d = directory, l = symlink
Tiga permission:
r(4) — baca isi file / list isi direktoriw(2) — tulis/ubah file / buat file di direktorix(1) — jalankan file sebagai program / masuk ke direktori dengancd
chmod
Cara mudah: notasi oktal (jumlahkan nilai r+w+x untuk setiap level).
chmod 755 script.sh # rwxr-xr-x: owner semua, group + others read+execute
chmod 644 config.json # rw-r--r--: owner read+write, lainnya read only
chmod 600 .env # rw-------: hanya owner yang bisa baca/tulis (sensitif!)
chmod 400 id_rsa # r--------: SSH private key, read only untuk owner
chmod 777 /tmp/shared # rwxrwxrwx: semua bisa semua (hindari kecuali perlu)
chmod +x deploy.sh # tambah execute untuk semua
chmod -w config.prod.js # hapus write permission untuk semua (jadikan read-only)
chmod u+x,g-w file.txt # owner: tambah execute; group: hapus write
chmod -R 755 public/ # rekursif untuk seluruh direktori| Oktal | Permission | Contoh penggunaan |
|---|---|---|
| 700 | rwx------ | direktori privat owner |
| 755 | rwxr-xr-x | script yang bisa dijalankan semua |
| 644 | rw-r--r-- | file konfigurasi, HTML, CSS |
| 600 | rw------- | .env, private config |
| 400 | r-------- | SSH private key |
chown
chown rinaldy file.txt # ubah owner
chown rinaldy:developers file.txt # ubah owner dan group
chown -R www-data:www-data /var/www/html # rekursif (untuk web server)sudo
sudo (superuser do) menjalankan perintah dengan privilege root. Gunakan hanya saat diperlukan — dengan great power comes great responsibility.
sudo apt update # update package list
sudo apt install nginx # install software
sudo systemctl restart nginx # restart service
sudo nano /etc/nginx/nginx.conf # edit config sistem
# Jangan lakukan ini kecuali kamu tahu persis apa yang terjadi:
# sudo rm -rf / ← menghapus seluruh sistem!
# sudo chmod -R 777 / ← semua orang bisa akses segalanyaBab 5: Proses & Background Jobs
Melihat Proses
ps aux # semua proses
ps aux | grep node # filter proses Node.js
ps aux | grep -v grep | grep node # exclude baris grep itu sendiri
top # interactive monitor (q: quit, k: kill, h: help)
htop # lebih bagus — warna, mouse, tree view (apt install htop)Kolom penting ps aux:
PID— Process ID, angka unik%CPU— persentase CPU%MEM— persentase RAMVSZ/RSS— virtual/resident memory usageSTAT— status: R(running), S(sleeping), Z(zombie), T(stopped)COMMAND— perintah yang menjalankan proses
Mengelola Proses
# Hentikan proses
kill 1234 # SIGTERM: minta berhenti dengan baik (bisa di-ignore)
kill -15 1234 # sama dengan kill, SIGTERM
kill -9 1234 # SIGKILL: paksa berhenti, tidak bisa di-ignore
killall node # hentikan semua proses bernama "node"
pkill -f server.js # hentikan proses yang command-nya mengandung "server.js"
# Shortcut di terminal
Ctrl+C # kirim SIGINT ke proses foreground (interrupt)
Ctrl+Z # suspend proses (kirim ke background, bisa dilanjutkan)
Ctrl+D # kirim EOF (tutup input, atau logout dari shell)Selalu coba kill (SIGTERM) dulu untuk graceful shutdown. Gunakan kill -9 hanya jika proses tidak merespons dalam beberapa detik.
Background Jobs
node server.js # foreground: terminal diblokir
node server.js & # background: terminal tetap bisa dipakai
# shell print PID: [1] 12345
jobs # lihat semua background jobs di session ini
fg # bawa job terakhir ke foreground
fg %1 # bawa job #1 ke foreground
bg # lanjutkan job suspended di background
bg %2 # lanjutkan job #2
# nohup: proses tetap jalan setelah logout
nohup node server.js > app.log 2>&1 &
disown # lepaskan proses dari shell (tidak terpengaruh logout)systemctl: Service Management
sudo systemctl start nginx # start
sudo systemctl stop nginx # stop
sudo systemctl restart nginx # stop + start
sudo systemctl reload nginx # reload config tanpa stop (kalau didukung)
sudo systemctl status nginx # status + log terbaru
sudo systemctl enable nginx # auto-start saat boot
sudo systemctl disable nginx # jangan auto-start
sudo systemctl is-active nginx # cek apakah sedang jalan
# Lihat log service via journalctl
sudo journalctl -u nginx -f # follow log nginx
sudo journalctl -u myapp --since "1 hour ago"
sudo journalctl -u myapp -n 100 # 100 baris terakhirBab 6: SSH: Masuk ke Server Remote
Dasar SSH
SSH (Secure Shell) mengenkripsi seluruh komunikasi antara laptop dan server. Default port: 22.
ssh username@ip-address
ssh rinaldy@103.28.12.45
ssh rinaldy@103.28.12.45 -p 2222 # port custom
ssh -v rinaldy@103.28.12.45 # verbose: debug koneksiPertama kali konek ke server baru, SSH menampilkan fingerprint dan minta konfirmasi. Ketik yes. Fingerprint disimpan di ~/.ssh/known_hosts.
SSH Key Authentication
Password SSH rentan brute force. SSH key pair jauh lebih aman.
Buat key pair:
# Buat key pair (ed25519 lebih modern dari RSA)
ssh-keygen -t ed25519 -C "rinaldy@backendlabs.id"
# Simpan di: ~/.ssh/id_ed25519 (default, tekan Enter)
# Passphrase: opsional tapi disarankan untuk keamanan ekstra
# Hasilnya:
# ~/.ssh/id_ed25519 ← PRIVATE KEY — jangan pernah share atau commit!
# ~/.ssh/id_ed25519.pub ← Public key — ini yang dikopikan ke serverKopikan public key ke server:
# Cara otomatis (paling mudah)
ssh-copy-id rinaldy@103.28.12.45
# Cara manual (jika ssh-copy-id tidak tersedia)
cat ~/.ssh/id_ed25519.pub | ssh rinaldy@103.28.12.45 \
"mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"Test:
ssh rinaldy@103.28.12.45 # harus bisa masuk tanpa passwordSSH Config: Shortcut
# ~/.ssh/config
Host backendlabs
HostName 103.28.12.45
User rinaldy
Port 22
IdentityFile ~/.ssh/id_ed25519
Host staging
HostName 103.28.12.99
User deploy
Port 2222
IdentityFile ~/.ssh/id_stagingssh backendlabs # = ssh rinaldy@103.28.12.45
ssh staging # = ssh deploy@103.28.12.99 -p 2222Transfer File dengan scp dan rsync
# scp: copy via SSH (simpel)
scp file.txt rinaldy@103.28.12.45:/home/rinaldy/ # upload
scp rinaldy@103.28.12.45:/var/log/app.log ./ # download
scp -r ./dist rinaldy@103.28.12.45:/var/www/myapp/ # upload direktori
# rsync: sync file, hanya kirim yang berubah (lebih efisien)
rsync -avz ./dist/ rinaldy@103.28.12.45:/var/www/myapp/
rsync -avz --delete ./dist/ rinaldy@103.28.12.45:/var/www/ # hapus file yang tidak ada di source
rsync -avzn ./dist/ server:/var/www/ # -n: dry run, lihat dulu apa yang akan berubahSSH Tunneling (Port Forwarding)
Berguna untuk mengakses service di server yang tidak di-expose ke internet:
# Local port forwarding: akses database server dari laptop
ssh -L 5433:localhost:5432 rinaldy@103.28.12.45
# Sekarang di laptop: psql -h localhost -p 5433 -U postgres
# → terhubung ke PostgreSQL di server melalui tunnel
# Background tunnel
ssh -fNL 5433:localhost:5432 rinaldy@103.28.12.45
# -f: fork to background, -N: no command (hanya forward)Bab 7: Package Management & Setup Environment
apt: Package Manager Linux (Debian/Ubuntu)
sudo apt update # update daftar package yang tersedia
sudo apt upgrade # upgrade semua package yang sudah diinstall
sudo apt install nginx # install package
sudo apt install git curl wget # install beberapa sekaligus
sudo apt remove nginx # hapus package
sudo apt autoremove # hapus package yang tidak diperlukan
apt search postgresql # cari package
apt show nodejs # info detail package
dpkg -l | grep nginx # cek apakah package terinstallHomebrew: Package Manager Mac
brew update # update Homebrew sendiri
brew install postgresql@16 # install
brew uninstall postgresql@16 # hapus
brew upgrade # upgrade semua
brew search redis # cari
brew info node # info
brew list # semua yang terinstall
brew services start postgresql@16 # jalankan sebagai service (auto-start)
brew services stop postgresql@16 # stop service
brew services list # list servicesnvm: Kelola Versi Node.js
Sangat berguna ketika project-project kamu pakai versi Node.js berbeda:
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# Restart terminal atau source ~/.bashrc
# Pakai nvm
nvm install 20 # install Node.js v20 (LTS)
nvm install 18 # install Node.js v18
nvm use 20 # pakai v20 untuk session ini
nvm alias default 20 # set v20 sebagai default
nvm ls # list versi yang terinstall
nvm current # versi yang sedang aktif
# .nvmrc: tentukan versi per project
echo "20" > .nvmrc
nvm use # baca dari .nvmrcBash Profile: Setup Environment
~/.bashrc (Linux) atau ~/.zshrc (Mac dengan Zsh) dijalankan setiap kali terminal baru dibuka. Tempat yang tepat untuk konfigurasi environment kamu:
# ~/.bashrc atau ~/.zshrc
# Alias: shortcut untuk perintah yang sering dipakai
alias ll='ls -la'
alias la='ls -A'
alias ..='cd ..'
alias ...='cd ../..'
alias gs='git status'
alias gp='git push'
alias gl='git log --oneline -20'
alias dc='docker compose'
alias dce='docker compose exec'
# Environment variables default
export EDITOR='nano' # editor default
export LANG='en_US.UTF-8'
export NODE_ENV='development'
# Tambahkan direktori ke PATH
export PATH="$HOME/.local/bin:$PATH"
export PATH="/usr/local/go/bin:$PATH" # Go
export PATH="$HOME/.cargo/bin:$PATH" # Rust
# Fungsi custom
mkcd() {
mkdir -p "$1" && cd "$1"
}
# Contoh: buat direktori sekaligus masuk ke dalamnya
# mkcd projects/new-apiSetelah edit .bashrc atau .zshrc, terapkan perubahan tanpa restart terminal:
source ~/.bashrc # atau
source ~/.zshrcBab 8: Tools Sehari-hari untuk Backend Developer
grep & Variasi
Sudah dibahas di Bab 3, tambahan:
# ripgrep (rg): grep yang jauh lebih cepat, sudah exclude .git dan node_modules
# Install: apt install ripgrep / brew install ripgrep
rg "console.log" ./src # cari di semua file source
rg -t js "TODO" # hanya file .js
rg --stats "error" app.log # statistik matchawk: Proses Kolom Data
awk sangat berguna untuk mengekstrak kolom tertentu dari output:
# Print kolom tertentu dari output ls -l
ls -l | awk '{print $5, $9}' # size dan filename
# Output: 4096 Documents
# Hitung total ukuran file dari ls -l
ls -l *.log | awk '{sum += $5} END {print sum, "bytes"}'
# Filter access log dan ambil IP address (kolom pertama)
cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
# Proses CSV sederhana
echo "name,age,city" > data.csv
echo "Rinaldy,28,Jakarta" >> data.csv
awk -F',' '{print $1, "lives in", $3}' data.csv
# Output: name lives in city
# Rinaldy lives in Jakartased: Ubah Teks
sed (stream editor) berguna untuk transformasi teks:
# Ganti semua occurance "localhost" dengan IP server
sed 's/localhost/103.28.12.45/g' config.template.js > config.js
# Edit file langsung (-i: in-place)
sed -i 's/NODE_ENV=development/NODE_ENV=production/g' .env
# Hapus baris yang mengandung kata tertentu
sed '/DEBUG/d' app.log > clean.log
# Tampilkan hanya baris tertentu
sed -n '10,20p' app.log # baris 10 sampai 20
# Hapus baris kosong
sed '/^$/d' messy.txtNetworking Tools
# ping: cek apakah host bisa dijangkau
ping google.com # ping terus-menerus (Ctrl+C untuk stop)
ping -c 5 google.com # hanya 5 kali
ping -c 1 103.28.12.45 # cek koneksi ke server
# curl: HTTP requests (detail di e-book #00)
curl -I https://backendlabs.id # hanya headers (HEAD request)
curl -s https://ipapi.co/json/ | python3 -m json.tool # IP info
# netstat / ss: lihat koneksi jaringan aktif
ss -tlnp # TCP listening, numeric, dengan PID
ss -tlnp | grep :3000 # siapa yang listen di port 3000?
netstat -tlnp # alternatif (mungkin perlu install net-tools)
# lsof: lihat file/port yang sedang dipakai
lsof -i :3000 # proses apa yang pakai port 3000?
lsof -i :5432 # cek PostgreSQL jalan di port 5432
lsof -p 1234 # semua file yang dibuka oleh PID 1234
# nmap: scan port (perlu install)
nmap -p 80,443,3000 103.28.12.45 # cek port mana yang terbukaDisk & Memory
df -h # free disk space semua partisi (human-readable)
df -h /var # hanya partisi /var
du -sh /var/log # total ukuran direktori
du -sh * # ukuran semua item di sini
du -sh * | sort -rh | head -10 # 10 terbesar
du -sh /var/lib/docker # ukuran data Docker
free -h # RAM: total, used, free, cached
# Temukan file besar yang memakan disk
find /var/log -name "*.log" -size +100M # log lebih dari 100MB
find / -xdev -size +1G 2>/dev/null # file lebih dari 1GBtar & Kompresi
# Buat archive
tar -czf backup.tar.gz ./myapp # gzip (cepat)
tar -cjf backup.tar.bz2 ./myapp # bzip2 (lebih kecil, lebih lambat)
tar -cJf backup.tar.xz ./myapp # xz (terkecil, paling lambat)
# Lihat isi tanpa ekstrak
tar -tzf backup.tar.gz
# Ekstrak
tar -xzf backup.tar.gz # di direktori saat ini
tar -xzf backup.tar.gz -C /tmp/restore/ # ke direktori tertentu
# Zip (lebih umum di ecosystem Windows)
zip -r archive.zip ./myapp
unzip archive.zip -d /tmp/extracted/Bab 9: Shell Script & Otomasi
Struktur Dasar Script
#!/bin/bash
# Shebang di baris pertama: tentukan interpreter
# Aktifkan mode strict (sangat direkomendasikan untuk semua script)
set -euo pipefail
# -e: exit jika ada perintah yang gagal
# -u: error jika variable tidak terdefinisi
# -o pipefail: pipeline gagal jika salah satu perintahnya gagal
# Variabel
APP_NAME="myapi"
APP_DIR="/var/www/${APP_NAME}"
TIMESTAMP=$(date +%Y%m%d_%H%M%S) # capture output perintah dengan $()
echo "Starting deployment of ${APP_NAME} at ${TIMESTAMP}"Simpan sebagai deploy.sh, beri izin eksekusi:
chmod +x deploy.sh
./deploy.shVariabel dan Input
#!/bin/bash
set -euo pipefail
# Positional arguments
APP_ENV=${1:-development} # $1 = argumen pertama, default "development"
APP_PORT=${2:-3000} # $2 = argumen kedua, default 3000
echo "Running in ${APP_ENV} on port ${APP_PORT}"
# Special variables
echo "Script name: $0"
echo "All args: $@"
echo "Arg count: $#"
echo "Last exit code: $?" # harus cek setelah setiap perintah
echo "Current PID: $$"
# Read dari user
read -p "Are you sure? (y/N): " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
echo "Cancelled."
exit 1
fiKondisional
#!/bin/bash
set -euo pipefail
ENV=${1:-development}
LOG_FILE="/var/log/myapp.log"
# If-elif-else
if [[ "$ENV" == "production" ]]; then
echo "Building for production..."
npm run build
NODE_ENV=production pm2 restart myapp
elif [[ "$ENV" == "staging" ]]; then
echo "Building for staging..."
npm run build
pm2 restart myapp-staging
else
echo "Starting development server..."
npm run dev
fi
# Cek apakah file ada
if [[ -f "$LOG_FILE" ]]; then
echo "Log file exists: $LOG_FILE"
fi
# Cek apakah direktori ada
if [[ ! -d "/var/www/myapp" ]]; then
echo "Directory not found! Creating..."
mkdir -p /var/www/myapp
fi
# Cek apakah command tersedia
if ! command -v node &> /dev/null; then
echo "Node.js not found! Please install it first."
exit 1
fiLoop
#!/bin/bash
set -euo pipefail
# Loop array
SERVICES=("nginx" "postgresql" "redis")
for SERVICE in "${SERVICES[@]}"; do
if systemctl is-active --quiet "$SERVICE"; then
echo "✓ ${SERVICE} is running"
else
echo "✗ ${SERVICE} is NOT running"
sudo systemctl start "$SERVICE"
fi
done
# Loop dengan counter
for i in {1..10}; do
echo "Attempt $i of 10..."
curl -sf http://localhost:3000/health && break
sleep 3
done
# Loop file
for log in /var/log/myapp/*.log; do
SIZE=$(du -sh "$log" | cut -f1)
echo "${log}: ${SIZE}"
done
# While loop
RETRIES=0
while ! curl -sf http://localhost:3000/health; do
RETRIES=$((RETRIES + 1))
if [[ $RETRIES -ge 10 ]]; then
echo "Health check failed after 10 retries!"
exit 1
fi
echo "Waiting for server... (attempt $RETRIES)"
sleep 2
done
echo "Server is healthy!"Fungsi
#!/bin/bash
set -euo pipefail
# Definisi fungsi
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
check_service() {
local SERVICE=$1 # local: variabel hanya ada di dalam fungsi
if systemctl is-active --quiet "$SERVICE"; then
log "✓ ${SERVICE} running"
return 0 # return value (exit code): 0 = success
else
log "✗ ${SERVICE} NOT running"
return 1
fi
}
backup_db() {
local DB_NAME=$1
local OUTPUT_DIR=${2:-/tmp/backups}
local TIMESTAMP=$(date +%Y%m%d_%H%M%S)
local OUTPUT_FILE="${OUTPUT_DIR}/${DB_NAME}_${TIMESTAMP}.sql.gz"
mkdir -p "$OUTPUT_DIR"
log "Backing up ${DB_NAME} to ${OUTPUT_FILE}..."
pg_dump -U postgres "$DB_NAME" | gzip > "$OUTPUT_FILE"
log "Backup complete: $(du -sh "$OUTPUT_FILE" | cut -f1)"
}
# Panggil fungsi
log "Deployment started"
check_service nginx || sudo systemctl start nginx
backup_db "myapp_production" "/var/backups/db"
log "Done"Deploy Script Lengkap
#!/bin/bash
set -euo pipefail
APP="backendlabs"
APP_DIR="/var/www/${APP}"
REPO="git@github.com:rinaldy/backendlabs.git"
BRANCH=${1:-main}
log() { echo "[$(date '+%H:%M:%S')] $*"; }
die() { echo "ERROR: $*" >&2; exit 1; }
log "Starting deployment of ${APP} (branch: ${BRANCH})"
# Cek dependencies
command -v node || die "Node.js not found"
command -v npm || die "npm not found"
command -v pm2 || die "pm2 not found"
# Pull code terbaru
log "Pulling latest code..."
cd "$APP_DIR"
git fetch origin
git checkout "$BRANCH"
git pull origin "$BRANCH"
# Install dependencies (hanya yang berubah)
log "Installing dependencies..."
npm ci --only=production
# Run migrations
log "Running database migrations..."
npm run migrate:up
# Restart aplikasi
log "Restarting application..."
pm2 restart "$APP" --update-env
# Health check
log "Waiting for health check..."
for i in {1..10}; do
if curl -sf http://localhost:3000/health; then
log "✓ Health check passed!"
break
fi
[[ $i -eq 10 ]] && die "Health check failed after 10 attempts!"
sleep 3
done
log "✓ Deployment complete!"cron: Jadwalkan Script
cron menjalankan perintah secara otomatis berdasarkan jadwal.
crontab -e # edit jadwal (otomatis pilih editor)
crontab -l # lihat jadwal saat ini
crontab -r # hapus semua jadwal (hati-hati!)Format: menit jam tanggal bulan hari_minggu perintah
# Backup database setiap hari jam 2 pagi
0 2 * * * /home/rinaldy/scripts/backup.sh >> /var/log/backup.log 2>&1
# Rotate log setiap Minggu jam 3 pagi
0 3 * * 0 /home/rinaldy/scripts/rotate-logs.sh
# Cek disk usage setiap jam, kirim alert jika > 80%
0 * * * * df -h / | awk 'NR==2{if ($5+0 > 80) print "DISK ALERT: "$5}' | mail -s "Disk Alert" admin@email.com
# Cleanup file temp setiap hari jam 1 pagi
0 1 * * * find /tmp -type f -mtime +7 -delete
# Setiap 5 menit
*/5 * * * * /path/to/script.sh
# Hanya hari kerja (Senin-Jumat) jam 9 pagi
0 9 * * 1-5 /path/to/weekday-report.shGunakan crontab.guru untuk membantu menulis dan memvalidasi jadwal cron.
Best practices cron:
- Selalu gunakan absolute path untuk perintah dan file
- Redirect output ke log file:
>> /var/log/myscript.log 2>&1 - Test script secara manual sebelum dijadwalkan
- Tambahkan
set -euo pipefaildi script yang dijadwalkan
Penutup
Terminal yang dulu terasa asing sekarang (semoga) terasa seperti alat yang bisa kamu andalkan. Dari ls dan cd yang paling dasar, sampai SSH ke server production dan deploy script otomatis — semua ini akan kamu pakai nyaris setiap hari.
Skill terminal tidak dikuasai dalam satu malam. Tapi semakin sering dipakai, semakin terasa alami. Mulai dengan menggantikan satu kebiasaan GUI dengan perintah terminal, lalu tambahkan satu per satu.
Checklist Pemahaman
- Bisa navigasi filesystem: cd, ls, pwd — paham absolute vs relative path
- Bisa membuat, menghapus, dan memindahkan file/direktori
- Mengerti format permission rwx dan bisa menggunakan chmod
- Bisa membaca dan menulis file: cat, less, head, tail -f, echo, nano
- Bisa mencari file dengan find dan mencari teks dengan grep
- Bisa SSH ke server remote menggunakan SSH key
- Bisa melihat dan menghentikan proses: ps, kill, systemctl
- Bisa install package dengan apt (Linux) atau brew (Mac)
- Tahu cara setup alias dan environment variable di .bashrc/.zshrc
- Bisa menulis shell script sederhana: variabel, kondisional, loop, fungsi
- Bisa menjadwalkan task dengan cron
Langkah Selanjutnya
- E-book #01 (Git & GitHub) — version control untuk semua kode yang akan kamu tulis
- E-book #05 (Docker) — Docker container berjalan di Linux, dan kamu sekarang punya fondasi untuk memahaminya dengan benar
- E-book #07 (Deploy VPS) — semua yang ada di e-book ini akan langsung terpakai saat kamu mengelola server production