Apa sebenarnya variabel lingkungan itu?

42

Saya tahu itu VARIABLE=valuemenciptakan variabel lingkungan, dan export VARIABLE=valuemembuatnya tersedia untuk proses yang dibuat oleh shell saat ini. envmenunjukkan variabel lingkungan saat ini, tetapi di mana mereka tinggal? Apa yang terdiri dari variabel lingkungan (atau lingkungan , dalam hal ini)?

Mat
sumber

Jawaban:

29

Sebuah lingkungan tidak semanis kelihatannya. Shell menyimpannya di memori dan beralih ke execve()panggilan sistem. Proses anak mewarisinya sebagai pointer array yang disebut environ. Dari halaman execvemanual:

RINGKASAN

   #include <unistd.h>

   int execve(const char *filename, char *const argv[],
              char *const envp[]);

argvadalah serangkaian string argumen yang diteruskan ke program baru.
Secara konvensi, string pertama harus berisi nama file yang terkait dengan file yang dieksekusi. envpadalah larik string, secara konvensional dari key key = value, yang dikirimkan sebagai lingkungan ke program baru.

Halaman environ(7)manual ini juga menawarkan beberapa wawasan:

RINGKASAN

   extern char **environ;

DESKRIPSI

Variabel environmenunjuk ke array pointer ke string yang disebut "lingkungan". Pointer terakhir dalam array ini memiliki nilai NULL. (Variabel ini harus dideklarasikan dalam program pengguna, tetapi dideklarasikan dalam file header <unistd.h>jika file header berasal dari libc4 atau libc5, dan dalam kasus mereka berasal dari glibc dan _GNU_SOURCE didefinisikan.) Array string ini tersedia untuk proses oleh panggilan exec (3) yang memulai proses.

Kedua manual GNU ini sesuai dengan spesifikasi POSIX

jordanm
sumber
4
+1 mungkin perlu dicatat bahwa beberapa anggota exec(3)keluarga (yaitu mereka yang tidak cocok dengan eksekutif * v) lulus ** lingkungan di bawah selimut.
msw
5
Perhatikan bahwa ini bukan tentang proses anak (proses anak mewarisi semua memori orang tua mereka), tetapi program yang dieksekusi (dalam proses yang sama), jadi ini merupakan cara lain untuk meneruskan data melalui panggilan sistem execve () (yang sebaliknya menghapus memori dari proses).
Stéphane Chazelas
@ msw: Ini adalah exec*evarian yang secara eksplisit melewati env, alih-alih secara implisit menggunakan environvariabel global. The vberarti "vektor", dan mengacu pada argumen baris perintah lulus sebagai array (bukan "daftar" (fungsi variabel-panjang)) execveadalah panggilan sistem, dan semua lainnya exec*fungsi pembungkus libc untuk itu.
Peter Cordes
19

Anda salah sedikit: SOME_NAME=valuemembuat variabel shell (di sebagian besar shell). export SOME_NAME=valuemenciptakan variabel lingkungan. Untuk yang lebih baik menjadi lebih buruk, kebanyakan shell Unix / Linux / * BSD menggunakan sintaksis yang identik dalam mengakses variabel lingkungan dan variabel shell.

Dalam arti yang lebih besar, "lingkungan" hanyalah informasi yang sejalan dengan eksekusi program. Dalam program C, Anda mungkin menemukan ID proses dengan getpid()panggilan, dalam program shell Anda akan menggunakan akses variabel: $$. ID proses hanyalah bagian dari lingkungan program. Saya percaya istilah "lingkungan" berasal dari beberapa topik ilmu komputer yang lebih teoritis, seperti pelaksanaan program pemodelan. Model pelaksanaan program memiliki lingkungan "yang berisi hubungan antara variabel dan nilai-nilai mereka".

Dan yang terakhir ini, definisi yang lebih kuat adalah apa "lingkungan" untuk shell Unix / Linux / * BSD: hubungan antara nama ("variabel") dan nilainya. Untuk sebagian besar kerang gaya Unix, nilainya semua string karakter, meskipun itu tidak sepenuhnya benar seperti dulu. Ksh, Zsh dan Bash semua memiliki variabel yang diketik hari ini. Bahkan definisi fungsi shell dapat diekspor.

Penggunaan lingkungan yang terpisah dari variabel shell biasa melibatkan fork/execmetode memulai proses baru yang digunakan semua Unix. Ketika Anda exportpasangan nama / nilai, pasangan nama / nilai itu akan hadir di lingkungan executable baru, dimulai oleh shell dengan execve(2)panggilan sistem (biasanya mengikuti a fork(2), kecuali ketika execperintah shell digunakan).

Berikut ini execve(), main()fungsi biner baru memiliki argumen baris perintah, lingkungan (disimpan sebagai array pointer yang diakhiri NULL ke var=valuestring, lihat environ(7)halaman manual). Keadaan lain yang diwariskan termasuk ulimitpengaturan, direktori kerja saat ini, dan deskriptor file terbuka yang execve()pemanggil tidak memiliki FD_CLOEXEC diatur untuk. Keadaan tty saat ini (diaktifkan echo, mode mentah, dll.) Juga dapat dianggap sebagai bagian dari kondisi eksekusi yang diwarisi oleh proses yang baru exec.

Lihat bashdeskripsi manual tentang lingkungan eksekusi untuk perintah sederhana (selain fungsi builtin atau shell).

Lingkungan Unix berbeda dari setidaknya beberapa sistem operasi lain: "leksikal" VMS dapat diubah oleh proses anak, dan perubahan itu terlihat pada induknya. VMS cddalam proses anak akan memengaruhi direktori kerja induk. Setidaknya dalam beberapa keadaan, dan ingatan saya mungkin mengecewakan saya.

Beberapa variabel lingkungan yang terkenal, $HOME, $PATH, $LD_LIBRARY_PATHdan lain-lain. Beberapa konvensional untuk sistem pemrograman tertentu, sehingga shell induk dapat memberikan banyak dan banyak informasi tujuan khusus untuk beberapa program, seperti direktori sementara tertentu, atau ID pengguna dan kata sandi yang tidak muncul di ps -ef. Program CGI sederhana mewarisi banyak informasi dari server web melalui variabel lingkungan, misalnya.

Bruce Ediger
sumber
1
Tampaknya masih sedikit lebih rumit. Dalam bash setidaknya SOME_NAME=value commandakan menetapkan variabel lingkungan SOME_NAME untuk permintaan perintah itu. Yang membingungkan, sepertinya tidak mengatur variabel shell dengan nama yang sama.
Samuel Edwin Ward
2
Untuk lebih tepatnya, variabel lingkungan tidak diwariskan tetapi secara eksplisit diteruskan dari shell ke program yang ditimbulkannya.
msw
2
@SamuelEdwinWard alasan bahwa Anda SOME_NAME=value commandberperilaku bertentangan dengan harapan Anda adalah bahwa itu adalah sintaks khusus yang berarti "tambahkan SOME_NAME ke lingkungan yang dikirimkan ke perintah tetapi jangan ubah variabel shell ini".
msw
1
Menarik, tautan ke kalkulus lambda / pemrograman fungsional. Itu koneksi yang menarik yang sangat masuk akal.
Matt
1
Beberapa di antaranya tidak tepat. Misalnya, subkulit yang subproses dan harus fork()ed, tetapi mereka lakukan menerima (salinan) variabel shell.
ruakh
7

Variabel lingkungan dalam bentuk paling mentah mereka hanya satu set pasangan nama / nilai. Seperti yang dijelaskan di halaman bash man ( man 1 bash) di bawah bagian LINGKUNGAN:

   When  a  program  is invoked it is given an array of strings called the
   environment.   This  is  a  list  of  name-value  pairs,  of  the  form
   name=value.

   The  shell  provides  several  ways  to manipulate the environment.  On
   invocation, the shell scans its own environment and creates a parameter
   for  each name found, automatically marking it for export to child pro-
   cesses.  Executed commands inherit the  environment.

Dalam istilah praktis, ini memungkinkan Anda untuk mendefinisikan perilaku yang dibagikan atau unik untuk program yang dipanggil dari shell saat ini. Misalnya, saat menggunakan crontabatau visudoAnda dapat mendefinisikan EDITORvariabel lingkungan untuk menentukan editor lain selain yang akan digunakan sistem Anda secara default. Hal yang sama dapat berlaku untuk hal-hal seperti manperintah yang melihat PAGERlingkungan Anda untuk mengetahui program pager apa yang harus digunakan untuk menampilkan output dari halaman manual.

Cukup banyak perintah unix membaca lingkungan dan tergantung pada apa yang diatur di sana, ubah output / pemrosesan / tindakan mereka tergantung pada ini. Beberapa dibagikan, beberapa unik untuk program ini. Sebagian besar halaman manual berisi informasi tentang bagaimana variabel lingkungan memengaruhi program yang dijelaskan.

Ilustrasi praktis lainnya adalah untuk hal-hal seperti sistem dengan beberapa pemasangan Oracle pada platform yang sama. Dengan pengaturan ORACLE_HOME, seluruh rangkaian perintah oracle (seperti yang dimuat dari PATHvariabel lingkungan Anda ) kemudian tarik pengaturan, definisi, pemetaan dan pustaka dari bawah direktori tingkat atas itu. Hal yang sama berlaku untuk program lain seperti java dengan JAVA_HOMEvariabel lingkungannya.

bash sendiri memiliki banyak variabel lingkungan yang dapat mengubah perilaku berbagai hal mulai dari riwayat ( HISTSIZE, HISTFILEdll), ukuran layar ( COLUMNS), penyelesaian tab ( FIGNORE, GLOBIGNORE) lokal dan pengkodean / dekode karakter ( LANG, LC_*), prompt ( PS1.. PS4), dan sebagainya (lagi mencari pengetahuan dari halaman bash man).

Anda juga dapat menulis skrip / program yang memanfaatkan variabel lingkungan kustom Anda sendiri (untuk lulus pengaturan, atau mengubah fungsionalitas).

Drav Sloan
sumber
0

"Variabel Lingkungan" adalah seperangkat nilai bernama dinamis yang dapat memengaruhi cara proses yang berjalan akan berperilaku di komputer.

Mereka adalah bagian dari lingkungan operasi tempat suatu proses berjalan. Misalnya, proses yang berjalan dapat meminta nilai variabel lingkungan TEMP untuk menemukan lokasi yang cocok untuk menyimpan file sementara, atau variabel HOME atau USERPROFILE untuk menemukan struktur direktori yang dimiliki oleh pengguna yang menjalankan proses.

Info lebih lanjut di sini → http://en.wikipedia.org/wiki/Environment_variable .

Segala sesuatu yang ingin Anda ketahui tentang Variabel Lingkungan ... ↑

SoCalDiegoRob
sumber
1
Meskipun tidak mungkin tautan ini hilang, lebih baik menjawab pertanyaan di sini dengan teks yang relevan dan memberikan tautan sebagai tambahan untuk informasi cadangan.
Anthon
@Anthon Saya yakin Anda benar dan saya akan melakukan perubahan secepat mungkin ... Terima kasih atas
sarannya
-1

Jawaban ini membutuhkan beberapa pengalaman dan pengetahuan skrip shell dengan variabel istilah, nilai, penggantian variabel, prompt, echo, kernel, shell, utilitas, sesi dan proses.

Sebuah variabel lingkungan (envar) adalah satu set variabel yang didefinisikan global yang dapat mempengaruhi cara proses tertentu akan berperilaku pada sistem operasi komputer.

1. Pengantar teladan:

Kami mengganti utusan dengan huruf a $dan huruf kapital . Sebagai contoh: $PS1.

Kami dapat mencetak envar dengan cara ini:

echo $PS1

$PS1memegang nilai prompt Unix. Katakanlah nilai asalnya \u \w $.

  • \u singkatan dari pengguna (saat ini),
  • \w singkatan direktori kerja,
  • $ adalah untuk membatasi prompt.

Jadi, jika kita lakukan:, echo $PS1kita melihat nilai-nilai \u, \wditambah tanda dolar pada akhirnya.

Kita bisa mengubah perilaku Unix dalam konteks itu, jika kita mengubah nilai envar itu. Sebagai contoh:

PS1="\w >"

Sekarang prompt tampak seperti ini (dengan asumsi direktori kerja bernama "John"):

John >

Dengan cara yang sama yang bisa kita lakukan PS1="Hello, I'm your prompt >", maka echo $PS1akan membawa:

Hello, I'm your prompt >

Di Bash 4.xx, kita bisa mencetak SEMUA envars di sistem dengan envperintah. Saya sarankan mengeksekusi envdi terminal dan melihat outputnya.

2. Bagaimana data ini ditampilkan dan dimanipulasi:

Terminal sesi mari kita untuk menyesuaikan envars yang datang dengan Bash.

Perubahan yang disebutkan di atas biasanya bersifat sementara, dan inilah alasannya:

Setiap sesi (yang bukan merupakan sub-sesi) adalah unik, dan beberapa proses dapat berjalan secara unik pada waktu yang sama (masing-masing dengan set envars sendiri) tetapi biasanya ada warisan dari sesi 0 hingga sesi 1 dan ke atas.

Perubahan yang kami buat pada satu proses adalah unik untuknya, dan akan berhenti jika kami menutupnya tanpa menyimpannya dengan cara tertentu.

Jadi bagaimana kita menyimpan perubahan ini:

Ada beberapa jenis cara yang tersedia untuk menyimpan perubahan envar, tergantung pada ruang lingkup yang kami pilih. Berikut ini cakupan (level) yang berbeda untuk perubahan tersebut:

  • Level proses: Envars hanya tersedia untuk program di sesi saat ini.
  • Tingkat ekspor: The envars yang tersedia untuk program dalam sesi saat ini, atau semua yang sub-sesi.
  • Tingkat global: Perubahan akan disimpan untuk semua sesi apa pun (primer dan semua subs).

Di mana data envar disimpan:

Unix dibangun dari 3 lapisan utama: Kernel, shell, dan utilitas. AFAIK setiap shell memiliki envars sendiri, dan ini dibangun terutama atau secara eksklusif di shell.

Lokasi spesifik untuk mengubahnya secara global biasanya /etc/profilemeskipun kita juga bisa melakukannya .bashrctentunya.

3. Membuat envars baru:

Kita dapat membuat envars baru dan inilah caranya; pada Bash 4.xx tidak ada nama asli enavar MESSAGE(seperti yang dikatakan, para envars biasanya ditulis dalam huruf besar).

MESSAGE="Hello world!"

akan membuatnya untuk kita, dan sekarang jika kita mengetik gema $MESSAGE, kita dapatkan hello world!.

Jika kami akan mengeksekusi bashdi sesi kerja kami saat ini (jendela), kami akan memulai sub-sesi bash baru dan tidak akan lagi bekerja dalam proses asli, kecuali kami mengeksekusi exit.

Catatan: Dalam sistem operasi dengan emulator terminal (seperti desktop Ubuntu), sub-sesi biasanya berjalan di jendela yang sama, tetapi sesi baru di jendela lain bukanlah sub-sesi dari yang sudah ada (ini adalah proses yang berdekatan ) .

Catatan: Jangan gunakan tanda khusus dalam nilai envar seperti! atau mereka tidak akan diselamatkan.

Mengekspor envar dari sesi awal ke semua sub-sesi:

Kita masih dapat menggunakan envar yang dibuat di sesi pertama, di sesi kedua juga, tanpa mendaftarkannya di file konfigurasi pengguna atau tingkat global (lihat data berikut). Berikut cara melakukannya:

Buka sesi asli (apakah pada jendela saat ini atau yang lain) dan jalankan:

export MESSAGE

saat mengekspor, jangan gunakan $tanda.

Sekarang diekspor ke semua sub-sesi. Jika Anda akan melakukannya echo $MESSAGEpada sub-sesi, apakah dari pengguna Anda atau yang lain, maka akan dicetak.

Perhatikan bahwa variabel internal Shell seperti PS1tidak boleh diekspor, tetapi jika Anda ingin mengekspornya dari alasan apa pun dan tidak muncul, jangan jalankan bashsetelahnya export, tetapi lakukan bash –norc.

4. The $ PATH envar:

$PATH adalah envar yang paling sering diubah pengguna.

Jika kita echo $PATH, kita akan melihat aliran ini:

/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Nilai cetakan envar ini dipisahkan oleh titik dua (:) di sana, tapi di sini ada cara yang berpotensi lebih nyaman (ini adalah nilai yang sama ):

/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games

Ini adalah direcotries untuk mencari, ketika kita menjalankan utilitas.

Dengan mengeksekusi which echokita akan mendapatkan lokasi file - misalnya, kita mungkin melihatnya ada di /bin/echo.

Berdasarkan itu kita tidak perlu mengetikkan echo envar untuk melihat nilai evnar. Kami juga dapat melakukan:

/bin/echo $ENVAR

Envar masih akan dieksekusi, misalnya:

/bin/echo $HOME

Memberi kita

/home/User || /root

Sama seperti:

echo $HOME

Memberi kita

/home/User || /root

Catatan: $HOMEdisingkat ~.

System- $ PATH relations, dan kemungkinan interaksi pengguna:

Dalam Bash 4.xx, ketika kita menggunakan utilitas tanpa path lengkapnya, sistem akan menggunakan semua 6 nilai yang disebutkan di atas, dari $PATHenvar. Jadi, itu akan mulai dari /user/local/bin, dan akan mengikuti semua kontennya mencari yang echodapat dieksekusi.

Dalam hal ini, itu akan berhenti di /bin/echo, di mana, dalam hal ini, executable berada.

Oleh karena itu, alasan utama kita dapat menyesuaikan $PATHenvar, adalah menginstal executable yang tidak berada di bawah nilai asalnya.

Setelah menginstal executable tersebut, kita harus menetapkan $PATHnilainya sesuai dan kemudian kita akan dapat bekerja dengannya.

5. Lampiran - berkembang $PATH:

Kita dapat export $PATHmem-bash sub-sesi (yang mencakup ekstensi bash seperti WP-CLI untuk WordPress atau Drush untuk Drupal) dengan cara ini:

export PATH="/home/John:$PATH"

Ini akan menambahkan nilai baru /home/Johnke $PATH, dan kemudian setelah itu, itu akan melampirkan nilai-nilai asli padanya (tepat setelah titik dua), yang disimpan di bawah sintaks $PATH.

Perubahan permanen tersebut dapat dilakukan dalam skrip yang relevan, biasanya /etc/profiledengan nama .bashrc.

JohnDoea
sumber
3
Ada banyak sekali kesalahan dengan jawaban ini: penyatuan sesi dan proses, peringatan tentang !nilai variabel lingkungan yang tidak berfungsi yang tepat di bawah contoh yang menunjukkan itu berfungsi, gagasan salah sub-sesi, saran yang cukup aneh tentang apa yang harus dilakukan setelah mengekspor variabel shell, dan gagasan keliru tentang variabel lingkungan global.
JdeBP
warning about ! in an environment variable value not working that is right below an example showing it working? Tolong contoh.
JohnDoea
quite bizarre advice about what to do after exporting a shell variable, apa sebenarnya maksud Anda?
JohnDoea
false notion of global environment variables, apa sebenarnya maksud Anda?
JohnDoea