Belajar Zsh - Environment & PATH Management
Series/Belajar Zsh/Episode 15
Episode 15 of 23

Belajar Zsh - Environment & PATH Management

Mengelola environment Zsh dengan benar: perbedaan $PATH dan $path sebagai tied array, dedupe otomatis dengan typeset -U, guard [ -d ] sebelum menambah direktori ke path, ekspor variabel environment, serta modul zsh/datetime dan zsh/mathfunc untuk skrip yang butuh waktu dan kalkulasi numerik

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 14 kalian memahami async, jobs, dan piping, pada episode ini kita membahas bagian yang paling sering diremehkan tetapi paling sering menjadi sumber bug aneh: environment dan manajemen PATH. Pesan error seperti command not found di cron, atau skrip yang berjalan saat manual tapi gagal di scheduler, hampir selalu berakar pada manajemen environment yang salah.

Zsh memberi alat yang tidak dimiliki bash untuk masalah ini: tied array ($PATH/$path), typeset -U untuk dedupe otomatis, dan modul seperti zsh/datetime dan zsh/mathfunc. Kuasai bab ini dan kalian akan menyelesaikan 90% masalah "kenapa skripnya beda hasil" dalam karier kalian.

PATH: String, dan path: Array

Ingat tied array dari episode 4: $PATH adalah skalar (string dengan :), $path adalah array. Keduanya terhubung — mengubah satu mengubah yang lain.

Lihat keduanya
print $PATH
print -l $path

Manipulasi path sebagai array jauh lebih aman:

Tambah ke path
path=(~/bin $path)
path+=($HOME/.local/bin)
export PATH

Perhatikan: setelah mengubah path, perlu export PATH agar shell anak dan skrip melihatnya (karena path saja tidak diwariskan). Pola yang banyak dipakai:

Pattern tambah path yang benar
export PATH="$HOME/.local/bin:$PATH"

typeset -U: Dedupe Otomatis

Kesalahan umum: menambahkan path yang sama berulang kali (misal setiap sesi). Zsh punya solusi elegan: typeset -U membuat array hanya menyimpan nilai unik — duplikat otomatis dibuang saat ditambahkan.

Dedupe otomatis
typeset -U path
path+=(~/bin)
path+=(~/bin)        # sudah ada, diabaikan
print -l $path       # ~/bin hanya sekali

Ini fitur yang sangat dicintai: tidak perlu menulis guard manual untuk memeriksa keberadaan duplikat. typeset -U juga umum dipakai untuk cdpath, fpath, dan manpath.

Guard [ -d ]: Jangan Tambah Path yang Tidak Ada

Tambah path yang tidak ada = command not found yang membingungkan, dan path yang salah bisa "menang" dari path yang benar. Guard standar:

Guard sebelum menambah path
add_to_path() {
    local dir="$1"
    if [[ -d "$dir" && -r "$dir" ]]; then
        path+=("$dir")
        export PATH
    fi
}
 
add_to_path "$HOME/.local/bin"
add_to_path "$HOME/go/bin"
add_to_path "/opt/scripts"

Dengan guard ini, direktori yang belum ada tidak masuk PATH — mencegah typos dan mencegah path dari tool yang belum diinstall ikut "mengacaukan" lookup.

Tip

Kombinasi terbaik: typeset -U path (dedupe) + function add_to_path dengan guard [ -d ] (validasi). Ini pattern yang dipakai banyak dotfiles profesional dan menghilangkan seluruh kelas bug PATH.

Export Variabel Environment

Environment yang diwariskan ke proses anak harus di-export. Dua cara:

Cara export
# cara 1: set lalu export
EDITOR=nvim
export EDITOR
 
# cara 2: export langsung
export LANG=en_US.UTF-8
export KUBECONFIG="$HOME/.kube/config"
 
# cara 3: export + assignment satu baris (khas zsh)
export DB_HOST=localhost DB_PORT=5432

Variabel untuk Satu Perintah Saja

Untuk menyetel variabel hanya untuk satu perintah, prefix perintah:

Env per-perintah
DEBUG=1 ./deploy.sh
KUBE_CONTEXT=prod kubectl get pods

Ini tidak mencemari environment sesi — sangat berguna saat debug dan testing.

Di Mana Menaruh Export: zshenv vs zshrc

Ingat startup files di episode 2. Variabel environment yang harus ada di semua mode (termasuk skrip non-interaktif) sebaiknya ditaruh di ~/.zshenv, bukan .zshrc:

zshenv untuk env global
# ~/.zshenv
export EDITOR=nvim
export LANG=C.UTF-8
export HISTFILE="$HOME/.zsh_history"

zsh -c 'print $EDITOR' akan membaca zshenv — tetapi zsh -i -c (interaktif) akan membaca keduanya. Ini mencegah bug "variabel tidak ada di cron" yang menyiksa.

Warning

Jangan menaruh prompt, alias, atau binding di zshenv — ia dibaca oleh shell non-interaktif juga, sehingga skrip bisa "kotor" dengan function yang tidak perlu. Aturan emas: zshenv hanya variabel dan fungsi yang benar-benar dibutuhkan di mana-mana.

Modul zsh/datetime: Waktu di Skrip

Modul zsh/datetime menyediakan variabel EPOCHSECONDS (waktu Unix) dan function strftime bawaan:

Aktifkan zsh/datetime
zmodload zsh/datetime
Pakai EPOCHSECONDS & strftime
print $EPOCHSECONDS                    # 1755385200 (epoch)
strftime '%Y-%m-%d %H:%M:%S' $EPOCHSECONDS
 
# timestamp untuk nama file backup
backup_name="backup_$(strftime '%Y%m%d_%H%M%S').tar.gz"
print $backup_name
 
# math dengan epoch
start=$EPOCHSECONDS
sleep 2
print "Durasi: $((EPOCHSECONDS - start)) detik"

Ini mengalahkan memanggil binary date eksternal di dalam loop — EPOCHSECONDS adalah variabel, tidak ada proses fork. Untuk skrip yang mengukur durasi atau membuat timestamp, ini pola yang tepat.

Modul zsh/mathfunc: Kalkulasi Numerik

Modul zsh/mathfunc menyediakan fungsi matematika untuk (( )) dan $(( )):

Aktifkan zsh/mathfunc
zmodload zsh/mathfunc
Pakai mathfunc
print $(( 2.5 ** 3 ))      # 15.625
print $(( sin(3.14) ))     # ~0.00159
print $(( ceil(2.3) ))     # 3
print $(( sqrt(16) ))      # 4
Float di skrip
zmodload zsh/mathfunc
usage=$(du -sk /var/log | awk '{print $1}')
print "Ukuran dalam GB: $(( usage / 1024.0 ))"

Zsh 5.9 mendukung floating point arithmetic native di (( )). Perpaduan zsh/mathfunc dan EPOCHSECONDS membuat skrip bisa melakukan timing, kalkulasi persentase, dan konversi unit tanpa tool eksternal.

Parameter Module: zsh/parameter

Modul zsh/parameter memberikan akses terprogram ke struktur shell — array associative yang berisi info tentang parameter, fungsi, alias, dll:

Aktifkan zsh/parameter
zmodload zsh/parameter
Pakai zsh/parameter
print ${(k)aliases}        # semua alias
print ${(k)functions}      # semua function yang terdefinisi
print $parameters[PATH]    # skalar/array/tied
print $functions[compinit] # isi definisi compinit

Berguna untuk tooling dan debug: misalnya memeriksa apakah sebuah function sudah dimuat, atau mendaftar semua alias untuk dokumentasi otomatis.

Common Pitfalls

  • Lupa exportpath diubah tapi tidak di-export; shell anak tidak melihat perubahan.
  • PATH kosong saat init — jika .zshrc menimpa PATH=... (bukan menambah), semua perintah dasar hilang; selalu gunakan += atau prefix.
  • Dedupe manual berantakan — ganti dengan typeset -U path.
  • Menambah path tidak ada — guard dengan [[ -d "$dir" ]] seperti di atas.
  • zsh/datetime tidak aktifEPOCHSECONDS tidak terdefinisi sampai zmodload zsh/datetime dijalankan.

Penutup

Inti yang harus dibawa pulang:

  • $PATH skalar, $path array — tied array; manipulasi via array, jangan lupa export PATH.
  • typeset -U path menghapus duplikat otomatis.
  • Guard [[ -d ]] sebelum menambah direktori ke path.
  • zmodload zsh/datetime (EPOCHSECONDS, strftime) dan zsh/mathfunc (sin, ceil, float) untuk skrip yang butuh waktu dan kalkulasi.

Di episode 16 selanjutnya kita akan membahas error handling & debugging — menangkap error dengan trap (ERR/EXIT), opsi errexit, memahami exit codes, lalu debugging dengan zsh -x, zsh -n, print -P/print -l, dan which -f. Sampai jumpa di episode 16!

Belajar Zsh - Environment & PATH Management | Belajar Zsh