Variabel lingkungan

Variabel lingkungan dengan export, manipulasi PATH, dan penetapan env untuk satu perintah.

Daftar isi

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.

bash
VAR_NILAI=42
bash -c 'echo "nilai: $VAR_NILAI"'
export VAR_NILAI=42
bash -c 'echo "nilai: $VAR_NILAI"'
unset VAR_NILAI
text Keluaran
nilai: 
nilai: 42

Baris 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.

bash
env VAR_A=satu VAR_B=dua bash -c 'echo "$VAR_A dan $VAR_B"'
echo "di shell: [$VAR_A]"
text Keluaran
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.

bash
env -i bash -c 'echo "HOME: [$HOME]"'
env -i PATH=/usr/bin bash -c 'echo "PATH: [$PATH]"'
text Keluaran
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.

bash
mkdir -p latihan-bin
printf '#!/usr/bin/env bash\necho "sapa dari direktori latihan-bin"\n' > latihan-bin/sapa
chmod +x latihan-bin/sapa

Tanpa 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.

bash
sapa 2>/dev/null
echo "kode keluar tanpa PATH: $?"
(PATH="$PWD/latihan-bin:$PATH"; sapa)
text Keluaran
kode keluar tanpa PATH: 127
sapa dari direktori latihan-bin

Nilai 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.

bash
PATH="$PWD/latihan-bin" bash -c 'ls' 2>/dev/null
echo "kode keluar: $?"
text Keluaran
kode keluar: 127

Shell 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 export atau penetapan awal, variabelnya tidak pernah masuk lingkungan. Tandai dengan export bila 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 +x pada 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 menafsirkan dua sebagai perintah terpisah, sehingga nilai yang mengandung spasi harus dilindungi tanda kutip.

Ringkasan#

  • Variabel shell hanya hidup di sesinya, sedangkan export menyalinnya ke lingkungan proses anak yang diluncurkan sesudahnya.
  • Penetapan awal NAMA=nilai perintah dan perintah env membatasi variabel untuk satu proses, dan env -i memulai dari lingkungan kosong.
  • PATH berisi 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#