Apa perbedaan antara set, ekspor dan env dan kapan saya harus menggunakan masing-masing?

112

Seringkali saya akan mem-bash skrip bash dan menurut saya ada beberapa cara menetapkan variabel:

key=value
env key=value
export key=value

Ketika Anda berada di dalam skrip atau perintah tunggal (misalnya, saya akan sering rantai variabel dengan peluncur Wine untuk menetapkan awalan Wine yang tepat) ini tampaknya benar-benar dipertukarkan tetapi tentu saja itu tidak bisa terjadi.

Apa perbedaan antara ketiga metode ini dan dapatkah Anda memberi saya contoh kapan saya secara khusus ingin menggunakan masing-masing metode tersebut?

Jelas terkait dengan Apa perbedaan antara `VAR = ...` dan `export VAR = ...`? tapi saya ingin tahu seberapa envcocok dengan ini juga, dan beberapa contoh yang menunjukkan manfaat masing-masing akan menyenangkan juga :)

Oli
sumber
5
Perhatikan bahwa export key=valueini adalah sintaks yang diperluas dan tidak boleh digunakan dalam skrip portabel (yaitu #! /bin/sh).
Simon Richter

Jawaban:

110

Mari kita perhatikan contoh spesifik. The grepperintah menggunakan variabel lingkungan yang disebut GREP_OPTIONSuntuk mengatur opsi default.

Sekarang. Mengingat bahwa file tersebut test.txtberisi baris-baris berikut:

line one
line two

menjalankan perintah grep one test.txtakan kembali

line one

Jika Anda menjalankan grep dengan -vopsi, itu akan mengembalikan garis yang tidak cocok, sehingga hasilnya akan menjadi

line two

Kami sekarang akan mencoba untuk mengatur opsi dengan variabel lingkungan.

  1. Variabel lingkungan yang ditetapkan tanpa exporttidak akan diwarisi dalam lingkungan perintah yang Anda panggil.

    GREP_OPTIONS='-v'
    grep one test.txt
    

    Hasil:

    line one

    Jelas, opsi -vtidak diteruskan grep.

    Anda ingin menggunakan formulir ini ketika Anda menetapkan variabel hanya untuk shell untuk digunakan, misalnya di for i in * ; doAnda tidak ingin mengekspor $i.

  2. Namun, variabel diteruskan ke lingkungan baris perintah tertentu, sehingga Anda dapat melakukannya

    GREP_OPTIONS='-v' grep one test.txt

    yang akan mengembalikan yang diharapkan

    line two

    Anda menggunakan formulir ini untuk sementara waktu mengubah lingkungan dari program khusus yang diluncurkan ini.

  3. Mengekspor variabel menyebabkan variabel diwariskan:

    export GREP_OPTIONS='-v'
    grep one test.txt
    

    kembali sekarang

    line two

    Ini adalah cara paling umum pengaturan variabel untuk penggunaan proses selanjutnya dimulai dalam shell

  4. Ini semua dilakukan dalam bash. exportadalah bash builtin; VAR=whateveradalah sintaks bash. env, di sisi lain, adalah program itu sendiri. Ketika envdipanggil, hal-hal berikut terjadi:

    1. Perintah envdijalankan sebagai proses baru
    2. env memodifikasi lingkungan, dan
    3. memanggil perintah yang disediakan sebagai argumen. The envProses digantikan oleh commandproses.

    Contoh:

    env GREP_OPTIONS='-v' grep one test.txt

    Perintah ini akan meluncurkan dua proses baru: (i) env dan (ii) grep (sebenarnya, proses kedua akan menggantikan yang pertama). Dari sudut pandang grepproses, hasilnya persis sama dengan menjalankan

    GREP_OPTIONS='-v' grep one test.txt

    Namun, Anda dapat menggunakan idiom ini jika Anda berada di luar bash atau tidak ingin meluncurkan shell lain (misalnya, ketika Anda menggunakan rangkaian exec()fungsi alih-alih system()panggilan).

Catatan tambahan aktif #!/usr/bin/env

Ini juga mengapa idiom #!/usr/bin/env interpreterdigunakan daripada #!/usr/bin/interpreter. envtidak memerlukan path lengkap ke suatu program, karena ia menggunakan execvp()fungsi yang mencari melalui PATHvariabel seperti halnya shell, dan kemudian menggantikan dirinya dengan perintah run. Dengan demikian, dapat digunakan untuk mencari tahu di mana seorang penerjemah (seperti perl atau python) "duduk" di jalan.

Ini juga berarti bahwa dengan memodifikasi jalur saat ini Anda dapat memengaruhi varian python mana yang akan dipanggil. Ini memungkinkan hal-hal berikut:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

alih-alih meluncurkan Calibre, akan menghasilkan

I am an evil interpreter!
Januari
sumber
Mengapa GREP_OPTIONS = '- v' grep satu test.txt berfungsi? Saya pikir itu perlu titik koma setelah '-v' (tapi saya mencobanya dan ternyata berhasil.)
Joe
2
Karena dengan titik koma, itu ditafsirkan sebagai dua perintah bash yang terpisah; yang pertama mengatur variabel (tanpa mengekspornya), dan yang kedua dimulai dengan lingkungan yang tidak memiliki variabel yang diekspor. Tanpa titik koma, bagaimanapun, ini adalah satu perintah (grep), didahului dengan menetapkan lingkungan lokal.
Januari
Dari mana semua variabel envberasal? Maksud saya ketika Anda membuka shell baru Anda selalu memiliki beberapa variabel. Jadi beberapa program harus sudah exportmengeditnya, kan?
Pithikos
1
Variabel @Pithikos Environment ditetapkan oleh "sumber lingkungan". Secara default, bash akan sumber bashrc seluruh sistem (atau profile.d atau bash_profile). Kemudian ia mengambil pengguna Anda ~ / .bashrc (dan / atau ~ / .bash_profile). Salah satu dari file-file ini dapat berisi perintah bash untuk sumber skrip lain, sehingga Anda akhirnya dapat memiliki variabel lingkungan yang datang dari semua tempat
Eric
5
Bagaimana dengan set var=blah?
CMCDragonkai