Setiap proses membawa daftar pasangan nama dan nilai yang disebut lingkungan (environment), dan daftar ini diwariskan dari proses induk ke proses anak pada saat proses diluncurkan. Shell menyediakan beberapa mekanisme untuk menetapkan variabel lingkungan, baik untuk seluruh sesi melalui export maupun untuk satu perintah saja melalui penetapan awal atau perintah env. Topik ini membahas ketiganya, ditutup dengan manipulasi PATH, yaitu variabel yang menentukan tempat shell mencari program yang dapat dijalankan.
Lingkungan proses dan pewarisan#
Variabel yang ditetapkan di shell tanpa export hanyalah variabel shell, yaitu milik sesi tersebut dan tidak pernah dilihat oleh proses anak. Barulah setelah ditandai dengan export, variabel itu ikut disalin ke lingkungan setiap proses anak yang diluncurkan sesudahnya. Pewarisan berjalan satu arah, sehingga perubahan lingkungan di dalam proses anak tidak pernah mengalir balik ke induknya.
Blok berikut membandingkan kedua bentuk tersebut. Perintah bash -c meluncurkan shell anak yang mencoba membaca variabel yang sama, sehingga perbedaannya terlihat langsung.
VAR_NILAI=42
bash -c 'echo "nilai: $VAR_NILAI"'
export VAR_NILAI=42
bash -c 'echo "nilai: $VAR_NILAI"'
unset VAR_NILAInilai:
nilai: 42Baris pertama mencetak kata nilai tanpa isi, karena shell anak menerima lingkungan yang belum memuat VAR_NILAI. Setelah export, salinan variabel ikut ke shell anak dan nilainya terbaca. Perintah unset di akhir menghapus variabel dari sesi sehingga bagian berikutnya dimulai dari keadaan bersih.
Menetapkan variabel untuk satu perintah#
Mengekspor variabel untuk keperluan satu perintah saja terasa berlebihan, karena itu shell menyediakan bentuk penetapan awal, yaitu menulis NAMA=nilai tepat sebelum nama perintah. Variabel itu hanya hidup selama perintah tersebut berjalan, dan lingkungan sesi tidak tersentuh sama sekali. Perintah env menawarkan bentuk yang lebih eksplisit dengan perilaku yang sama.
env VAR_A=satu VAR_B=dua bash -c 'echo "$VAR_A dan $VAR_B"'
echo "di shell: [$VAR_A]"satu dan dua
di shell: []Shell anak berhasil membaca kedua variabel, sedangkan sesi induk tetap tidak mengenal keduanya. Bentuk penetapan awal VAR_A=satu bash -c ... memberikan hasil yang identik dengan env, sehingga pilihannya hanya perkara keterbacaan. Kombinasi ini sering dipakai skrip untuk mengatur perilaku program anak tanpa mencemari lingkungan sesi.
Kasus yang lebih ekstrem adalah memulai dari lingkungan yang kosong. Opsi -i pada env menghapus seluruh lingkungan warisan, sehingga program anak berjalan hanya dengan variabel yang diberikan secara eksplisit. Cara ini dipakai untuk menguji program terhadap lingkungan yang terkontrol, misalnya memastikan program tidak diam-diam bergantung pada variabel lama.
env -i bash -c 'echo "HOME: [$HOME]"'
env -i PATH=/usr/bin bash -c 'echo "PATH: [$PATH]"'HOME: []
PATH: [/usr/bin]HOME yang biasanya terisi kini kosong, karena lingkungan yang diterima shell anak benar-benar polos. Pada baris kedua, PATH diisi ulang secara eksplisit agar shell anak tetap dapat menemukan programnya. Kosongnya lingkungan juga menjelaskan mengapa program yang diuji dengan env -i sering berperilaku berbeda dari biasanya.
PATH dan pencarian perintah#
Ketika sebuah perintah diketik tanpa menyebut jalur berkas, shell mencari programnya satu per satu di direktori yang terdaftar pada PATH. Urutan direktorinya berarti urutan prioritas, dan direktori pertama yang memuat program dengan nama yang cocok itulah yang dipilih. Apabila tidak ada satu pun direktori yang memuatnya, shell berhenti dengan kode keluar 127, yaitu kode konvensi untuk perintah yang tidak ditemukan.
Blok berikut menyiapkan skrip kecil bernama sapa di dalam direktori latihan-bin, lengkap dengan izin eksekusi. Skrip ini hanya berupa bahan uji untuk demonstrasi pencarian perintah.
mkdir -p latihan-bin
printf '#!/usr/bin/env bash\necho "sapa dari direktori latihan-bin"\n' > latihan-bin/sapa
chmod +x latihan-bin/sapaTanpa perluasan PATH, pemanggilan sapa gagal karena direktorinya tidak terdaftar. Kegagalan itu ditekan dengan redirection, dan kode keluar 127-nya ditampilkan secara eksplisit. Setelah itu, perluasan PATH dilakukan di dalam subshell, yaitu shell anak sementara, agar lingkungan sesi utama tidak berubah permanen.
sapa 2>/dev/null
echo "kode keluar tanpa PATH: $?"
(PATH="$PWD/latihan-bin:$PATH"; sapa)kode keluar tanpa PATH: 127
sapa dari direktori latihan-binNilai 127 muncul karena pencarian sapa di seluruh direktori PATH berakhir tanpa hasil. Dengan direktori latihan-bin diletakkan di depan, shell menemukan skrip dan menjalankannya. Pola PATH="$PWD/latihan-bin:$PATH" mempertahankan isi PATH lama dan hanya menambahkan satu direktori di depannya, dan inilah bentuk manipulasi PATH yang aman.
Blok berikut memperlihatkan akibat tersebut dalam bentuk kode keluar.
PATH="$PWD/latihan-bin" bash -c 'ls' 2>/dev/null
echo "kode keluar: $?"kode keluar: 127Shell anak yang PATH-nya hanya memuat latihan-bin gagal menemukan ls, dan kode keluar 127 menjadi satu-satunya petunjuknya. Lingkungan sesi utama tidak berubah karena manipulasi dilakukan pada proses anak. Agar berlaku permanen, perluasan PATH dituliskan pada berkas profil shell yang dibaca ketika sesi dimulai.
Kesalahan umum#
Kesalahan pada variabel lingkungan hampir selalu berupa salah paham tentang arah pewarisan. Daftar berikut memuat kekeliruan yang paling sering ditemui beserta perbaikannya.
- Mengira variabel shell otomatis dilihat oleh proses anak. Tanpa
exportatau penetapan awal, variabelnya tidak pernah masuk lingkungan. Tandai denganexportbila variabelnya memang diperuntukkan bagi program anak. - Mengekspor variabel dari dalam skrip dan berharap sesi induk ikut berubah. Pewarisan lingkungan berjalan satu arah dari induk ke anak. Cetak hasil yang diinginkan ke aliran keluaran sebagai gantinya.
- Melupakan
chmod +xpada skrip yang baru dibuat. Program tanpa izin eksekusi tidak dapat dijalankan meskipun direktorinya sudah terdaftar di PATH. - Menulis nilai dengan spasi tanpa tanda kutip, misalnya
VAR_A=satu dua. Shell menafsirkanduasebagai perintah terpisah, sehingga nilai yang mengandung spasi harus dilindungi tanda kutip.
Ringkasan#
- Variabel shell hanya hidup di sesinya, sedangkan
exportmenyalinnya ke lingkungan proses anak yang diluncurkan sesudahnya. - Penetapan awal
NAMA=nilai perintahdan perintahenvmembatasi variabel untuk satu proses, danenv -imemulai dari lingkungan kosong. PATHberisi daftar direktori yang dicek berurutan oleh shell saat mencari program, dan kegagalannya melaporkan kode keluar 127.- Manipulasi PATH yang aman menambahkan direktori di depan nilai lama dengan bentuk
PATH="/direktori:$PATH".
Referensi#
- GNU Bash Reference Manual — Free Software Foundation — Mengulas variabel shell, export, unset, dan variabel khusus PATH.
- GNU Coreutils Manual — Free Software Foundation — Mendokumentasikan env beserta opsi -i untuk lingkungan yang kosong.