Shell bukan sekadar tempat mengetik perintah — ia adalah jembatan antara kalian dan kernel. Episode ini membedah environment variables, kapan .bashrc dan .profile dieksekusi, cara mengkustomisasi prompt dan alias, hingga menulis script bash pertama dengan variabel, kondisional, dan loop.

Setelah di episode 11 sebelumnya kita membahas package management — apt, dnf, pacman, plus format universal snap/flatpak/AppImage — kalian sekarang bisa menginstal aplikasi apa pun ke sistem. Namun ada satu pertanyaan yang mengganggu sejak episode-episode awal: ketika kalian mengetik nginx, bagaimana Linux tahu harus mencari program nginx di direktori mana? Dan mengapa setiap terminal yang dibuka terasa "baru lagi", padahal konfigurasi sudah diubah?
Jawabannya ada di sebuah konsep yang hampir tidak terlihat padahal bekerja setiap detik: environment variables dan startup files. Pada episode kali ini, kita akan membedah cara kerja shell Bash — mulai dari variabel lokal vs environment, variabel-variabel kunci seperti PATH dan PS1, kapan .bashrc/.bash_profile dieksekusi, hingga menulis script bash pertama kalian. Di akhir episode, terminal kalian akan terasa "hidup" dengan kustomisasi sendiri. Mari kita mulai.
Sejak episode 2 kalian tahu arsitektur Linux berlapis: hardware → kernel → shell → user space. Shell adalah program yang membaca perintah kalian, menerjemahkannya, dan meminta kernel mengeksekusinya. Bash (Bourne Again Shell) adalah shell default di mayoritas distro. Ia bukan sekadar "tempat mengetik" — ia punya bahasa pemrograman sendiri yang bisa menangani variabel, logika, dan loop.
Salah satu model mental terbaik untuk memahami shell adalah dapur restoran. Shell adalah koki utama yang menerima pesanan (perintah) dari pelanggan (kalian). Di atas meja dapur ada resep-resep yang sudah ditulis (file script) dan bahan baku (variabel) yang siap dipakai kapan saja. Ketika kalian mengetik nginx, shell mencari resepnya di beberapa rak tertentu — dan rak-rak itulah isi dari variabel PATH.
Variabel di shell adalah pasangan nama=nilai. Bedanya ada dua jenis: variabel lokal (hanya dikenal shell saat ini) dan variabel environment (diwariskan ke program anak yang dijalankan dari shell tersebut).
# Variabel lokal — hanya dikenal di shell ini
NAMA="arman"
echo "Halo, $NAMA"
# Masih lokal — script tidak melihatnya
bash -c 'echo "dari child: $NAMA"' # output kosong!
# Export — kini diwariskan ke semua child process
export NAMA="arman"
bash -c 'echo "dari child: $NAMA"' # output: armanPerbedaan ini penting sekali untuk dipahami, karena ia adalah akar dari "missing export" — masalah yang hampir semua admin Linux pernah temui. Ketika sebuah program (misalnya aplikasi Node.js) membaca environment variable dan tidak menemukannya, itu biasanya karena variabel didefinisikan tanpa export, sehingga tidak pernah diwariskan ke child process. Ingat pola dasarnya: VAR=value hanya untuk shell ini, sedangkan export VAR=value untuk seluruh ekosistem proses turunannya.
Note
Singkatan VAR=x dengan VAR = x adalah dua hal berbeda! Yang pertama adalah penugasan variabel, yang kedua adalah menjalankan perintah bernama VAR dengan argumen = dan x. Selalu tulis tanpa spasi di sekitar tanda sama dengan.
Beberapa environment variable sudah diset otomatis oleh sistem dan dipakai terus-menerus. Mengenali mereka adalah modal besar untuk troubleshooting:
| Variabel | Fungsi | Contoh nilai |
|---|---|---|
PATH | Daftar direktori yang dicari saat mengetik perintah | /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin |
HOME | Direktori home user aktif | /home/arman |
USER | Nama user yang sedang login | arman |
LANG | Lokalisasi (bahasa & encoding) | en_US.UTF-8 |
PS1 | Template tampilan prompt | \u@\h:\w\$ |
PATH adalah bintang utamanya. Ketika kalian mengetik ls, shell memindai setiap direktori di PATH dari kiri ke kanan sampai menemukan ls. Perintah yang jalurnya tidak ada di PATH harus dipanggil dengan path lengkap, misalnya ./script.sh atau /opt/myapp/bin/tool. Inilah mengapa kalian sering melihat ./ sebelum menjalankan script — titik berarti "direktori saat ini", yang tidak selalu ada di PATH.
# Lihat PATH saat ini
echo "$PATH"
# Cek di direktori mana sebuah perintah berada
which nginx
# Tambahkan direktori kustom ke PATH (permanen lewat .bashrc)
export PATH="$PATH:$HOME/bin".bashrc, .bash_profile, dan .profileIni bagian yang paling sering membingungkan pemula. Ada beberapa file startup di home directory, dan masing-masing dieksekusi dalam kondisi yang berbeda. Perbedaan utamanya terletak pada dua jenis sesi shell:
Peta dieksekusinya kurang lebih begini:
| File | Login shell (TTY/SSH) | Non-login (terminal baru) | Dibaca juga oleh shell non-interaktif? |
|---|---|---|---|
/etc/profile | Ya (global) | Tidak | Tidak |
~/.bash_profile | Ya (jika ada) | Tidak | Tidak |
~/.profile | Ya (jika .bash_profile tak ada) | Tidak | Tidak |
~/.bashrc | Ya (biasanya dipanggil dari .bash_profile) | Ya | Tidak (kecuali diset) |
Tip
Aturan praktis yang aman: letakkan semua kustomisasi di ~/.bashrc, lalu pastikan ~/.bash_profile memanggilnya (baris [ -f ~/.bashrc ] && . ~/.bashrc sudah default di Ubuntu). Dengan begitu, alias dan fungsi kalian aktif baik di sesi login maupun setiap terminal baru. Jangan taruh perintah yang menampilkan output di .bashrc berlebihan — itu akan muncul di setiap terminal yang dibuka.
Mengapa ada dua file? Sejarahnya: .profile dirancang untuk login shell (mengatur environment), sedangkan .bashrc untuk shell interaktif baru. Sistem login biasanya hanya mengeksekusi .bash_profile, dan karena file itu jarang diubah, kebanyakan user tidak melihat kustomisasi .bashrc saat SSH login. Solusinya — lagi-lagi — adalah membuat .bash_profile memuat .bashrc.
Perhatikan juga shell lain punya file sendiri: .zshrc untuk Zsh (shell favorit developer modern, di episode sebelumnya kalian sudah berkenalan dengan Zsh lewat kustomisasi), dan .zshenv/.zprofile yang analog. Konsepnya sama: satu file untuk environment login, satu untuk setiap sesi interaktif.
Sekarang bagian yang menyenangkan. Alias adalah pintasan perintah; fungsi adalah mini-script di dalam shell. Keduanya diletakkan di .bashrc.
# Alias — pintasan singkat untuk perintah umum
alias ll='ls -lah'
alias gs='git status'
alias c='clear'
alias update='sudo apt update && sudo apt upgrade'
# Fungsi — logika yang melibatkan argumen & kondisi
function mkcd() {
mkdir -p "$1" && cd "$1"
}
function deploy() {
echo "Deploying ke produksi..."
# ... logika deploy
}Prompt kustom dikendalikan oleh PS1. Ini adalah template yang dirender setiap kali shell siap menerima perintah. Karakter \u, \h, \w masing-masing direplace dengan username, hostname, dan working directory. Contoh prompt yang menampilkan warna hijau untuk user biasa dan merah untuk root:
PS1='\[\e[32m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]$ 'Bagi kalian yang ingin hasil lebih canggih tanpa menulis kode warna manual, ekosistem starship atau oh-my-bash tersedia — tapi memahami PS1 manual tetap penting agar kalian bisa membaca template yang mereka hasilkan.
Untuk melihat bagaimana kustomisasi .bashrc berkembang, contoh diff berikut menambahkan dua alias dan memperbarui prompt — baris -- adalah baris lama, baris ++ adalah penggantinya:
alias ll='ls -l'
alias ll='ls -lah'
alias gs='git status'
PS1='\u@\h:\w\$ '
PS1='\[\e[32m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]$ 'Important
Setelah mengubah .bashrc, perubahan tidak berlaku otomatis di sesi yang sedang berjalan — .bashrc hanya dieksekusi saat shell baru dibuka. Jangan logout dulu; cukup jalankan source ~/.bashrc (atau . ~/.bashrc) untuk memuat ulang konfigurasi di sesi saat ini. Ini perintah penyelamat yang akan kalian pakai setiap hari.
Fungsi dan alias adalah kustomisasi interaktif; script adalah cara menulis logika yang bisa dijalankan berulang. Script bash hanyalah file teks berisi perintah shell, dengan baris pertama shebang #!/usr/bin/env bash yang memberi tahu kernel interpreter mana yang harus dipakai. Mari bangun satu script lengkap yang memakai semua elemen: argumen, variabel, kondisional, dan loop.
#!/usr/bin/env bash
# hello.sh — menyapa user dan menghitung file
NAMA="${1:-teman}" # argumen pertama, default "teman"
if [ -z "$NAMA" ]; then
echo "Tidak ada argumen diberikan."
fi
echo "Halo, $NAMA!"
for file in *.md; do
echo "Menemukan file markdown: $file"
done
echo "Total file di direktori ini:"
ls | wc -lMenjalankan script memerlukan izin eksekusi:
chmod +x hello.sh
./hello.sh arman
# Alternatif tanpa izin eksekusi: panggil interpreter secara eksplisit
bash hello.shSintaks kondisional if [ ... ] dan loop for ... in ... memakai struktur yang sama dengan bahasa pemrograman lain — bedanya, Bash menggunakan command sebagai kondisi ([ ] adalah singkatan dari perintah test). Spasi di sekitar kurung siku bukan sekadar gaya: [ -z "$NAMA" ] membutuhkan spasi setelah [ dan sebelum ], karena [ adalah nama perintah yang dipisahkan oleh spasi.
if [ "$USER" = "root" ]; then
echo "Dijalankan sebagai root"
else
echo "Dijalankan sebagai $USER"
fi
count=1
while [ $count -le 5 ]; do
echo "Iterasi ke-$count"
count=$((count + 1))
doneset, env, dan printenvKarena variabel ada di dua "dunia" — lokal dan environment — kalian juga butuh dua cara membaca yang berbeda. env (atau printenv) hanya menampilkan variabel yang diwariskan; set menampilkan semua variabel shell termasuk fungsi. Trik membedakannya adalah dasar dari banyak debugging:
# Hanya variabel environment (yang di-export)
env
printenv HOME
# Semua variabel shell + fungsi
set
# Cek satu variabel tanpa error jika tidak ada
echo "${HOME:-kosong}"Kesalahan yang paling sering terjadi terkait PATH adalah menimpanya alih-alih menambahkannya. Menulis export PATH="$HOME/bin" (tanpa $PATH di dalamnya) menggantikan seluruh daftar pencarian dengan satu direktori — akibatnya perintah dasar seperti ls, cat, bahkan sudo tidak lagi ditemukan. Selalu gunakan pola append: export PATH="$PATH:$HOME/bin".
Kesalahan kedua adalah mengedit file startup yang salah — menaruh alias di .bash_profile lalu bingung kenapa terminal baru tidak memuatnya (ingat: .bash_profile hanya untuk login shell), atau menaruh perintah output di .bashrc sehingga tiap tab membuka terminal memuntahkan teks.
Kesalahan ketiga adalah lupa export. Mendefinisikan DB_PASSWORD="rahasia" di terminal lalu menjalankan aplikasi yang membaca process.env.DB_PASSWORD — aplikasi tidak akan menemukannya karena variabel itu tidak pernah diwariskan. Gabungkan dengan kebiasaan mengecek dengan env atau printenv:
# Semua variabel environment
env
# Filter variabel tertentu
env | grep -i path
printenv PATH| Kesalahan | Gejala | Solusi |
|---|---|---|
PATH ditimpa, bukan ditambah | Perintah dasar tak ditemukan | export PATH="$PATH:$HOME/bin" |
Alias di .bash_profile | Tidak muncul di terminal baru | Pindah ke .bashrc |
Lupa export | Child process tidak melihat variabel | Gunakan export VAR=... |
Edit .bashrc tanpa source | Perubahan "tidak berefek" | source ~/.bashrc |
Spasi saat penugasan (VAR = x) | Perintah aneh "command not found: VAR" | Tulis tanpa spasi |
| Script tanpa shebang | Error "permission denied" atau dipakai shell salah | Mulai dengan #!/usr/bin/env bash |
Pada episode 12 ini kalian telah membangun pemahaman utuh tentang shell: membedakan variabel lokal dan environment dengan mekanisme export, mengenali variabel kunci seperti PATH, HOME, LANG, dan PS1, memahami kapan .bashrc/.bash_profile dieksekusi berdasarkan jenis sesi, mengkustomisasi prompt dan alias, serta menulis script bash pertama yang memuat argumen, kondisional, dan loop. Yang paling penting, kalian sekarang tahu mengapa konfigurasi tidak langsung aktif, mengapa PATH harus di-append, dan mengapa export menentukan siapa yang bisa melihat variabel.
Dengan terminal yang sudah "hidup" dan bisa ber-scripting, tibalah saatnya mengelola kekuatan sebenarnya dari sistem: proses. Di episode 13 selanjutnya kita akan membahas manajemen proses dan monitoring resource — PID dan PPID, state proses seperti zombie, ps/top/htop, sinyal SIGTERM/SIGKILL/SIGHUP, hingga menjalankan proses di background dengan nohup, screen, dan tmux. Sampai jumpa!