Mengekspor variabel env agar tersedia di semua subkulit, dan mungkin dapat dimodifikasi?

22

Misalkan saya punya

export MY_VAR=0

di ~/.bashrc.

Saya memiliki terminal gnome terbuka, dan di terminal ini, saya mengubah $MY_VARnilai menjadi 200. Jadi, jika saya lakukan

echo $MY_VAR

di terminal ini, 200ditampilkan.

Sekarang, saya membuka tab lain di terminal gnome saya, dan lakukan

echo $MY_VAR

... dan bukannya 200, saya punya 0.

Apa yang harus saya lakukan untuk mempertahankan nilai 200 ketika terminal memodifikasi variabel lingkungan, membuat modifikasi ini (pengaturan ke 200) tersedia untuk semua sub shell berikutnya dan semacamnya? Apakah ini mungkin?

Seseorang masih menggunakan Anda MS-DOS
sumber

Jawaban:

23

Sebuah salinan dari merambat lingkungan untuk sub-kerang, sehingga karya ini:

$ export MY_VAR=200
$ bash
$ echo $MY_VAR
200

tetapi karena ini adalah salinan, Anda tidak bisa mendapatkan nilai itu hingga shell induk - setidaknya dengan mengubah lingkungan.

Sepertinya Anda benar-benar ingin melangkah lebih jauh, yaitu membuat sesuatu yang bertindak seperti variabel global, dibagikan oleh cangkang "saudara" yang diprakarsai secara terpisah dari induk - seperti tab baru Anda di Terminal Gnome.

Sebagian besar, jawabannya adalah "Anda tidak bisa, karena variabel lingkungan tidak berfungsi seperti itu". Namun, ada jawaban lain, yaitu, Anda selalu dapat meretas sesuatu. Salah satu pendekatan adalah menulis nilai variabel ke file, seperti ~/.myvar, dan kemudian memasukkannya ke dalam ~/.bashrc. Kemudian, setiap shell baru akan mulai dengan nilai yang dibaca dari file itu.

Anda bisa melangkah lebih jauh - membuat ~/.myvardalam format MYVAR=200, dan kemudian mengatur PROMPT_COMMAND=source ~/.myvar, yang akan menyebabkan nilai dibaca kembali setiap kali Anda mendapatkan prompt baru. Itu masih belum cukup variabel global bersama, tapi itu mulai bertindak seperti itu. Itu tidak akan aktif sampai muncul kembali, yang tergantung pada apa yang Anda coba lakukan bisa menjadi batasan yang serius.

Dan kemudian, tentu saja, hal berikutnya adalah menulis perubahan secara otomatis ~/.myvar. Itu menjadi sedikit lebih rumit, dan saya akan berhenti pada titik ini, karena sungguh, variabel lingkungan tidak dimaksudkan sebagai mekanisme komunikasi antar-shell, dan lebih baik hanya mencari cara lain untuk melakukannya.

mattdm
sumber
10
Saya bisa mendengar cangkang memekik di bawah siksaan
Ya maaf Itu sebabnya saya berhenti. :)
mattdm
"yaitu membuat sesuatu yang bertindak seperti variabel global" - Ya, memang itulah yang saya coba selesaikan. The ~ / .myvar tidak cantik, tapi berhasil. Apakah Anda punya saran lain?
Seseorang masih menggunakan Anda MS-DOS
2
Baiklah, mari kita mundur sedikit. Mengapa Anda menginginkan variabel global?
mattdm
1
@mattdm: Saya punya "birokrasi" yang harus saya patuhi. Salah satunya adalah banyak kode yang perlu saya komit bersama dengan komentar. Kode-kode ini, sekarang, berada dalam hierarki folder (home / user / proyek / projectcode / code1 / code2). Saya membuat fungsi yang mengekstrak code1 dan code2 ke env vars (jadi ketika saya perlu melakukan suatu kegiatan, saya hanya memanggil fungsi di dalam dir dengan kode-kode), dan mereka, ketika melakukan, saya menggunakan vim dan ada beberapa fungsi yang baca vars ini dan berikan komentar secara otomatis. Saya pikir menggunakan file untuk itu bisa menjadi solusi.
Seseorang masih menggunakan Anda MS-DOS
13

Misalkan saya punya export MY_VAR=0di ~/.bashrc.

Itu kesalahanmu di sana. Anda harus mendefinisikan variabel lingkungan Anda ~/.profile, yang dibaca ketika Anda masuk. ~/.bashrcDibaca setiap kali Anda memulai shell; ketika Anda memulai shell bagian dalam, itu menimpaMY_VAR . Jika Anda belum melakukannya, variabel lingkungan Anda akan menyebar ke bawah.

Untuk informasi lebih lanjut tentang ~/.bashrcvs ~/.profile, lihat posting saya sebelumnya tentang topik ini .

Perhatikan bahwa propagasi ke atas (mendapatkan nilai yang dimodifikasi dari subkulit yang secara otomatis tercermin dalam shell induk) tidak dimungkinkan, berhenti sepenuhnya.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
3

Jangan gunakan variabel lingkungan sama sekali. Gunakan file.

Untuk mencegah proses saling menginjak ketika memperbarui / membaca file, gunakan kunci file dan skrip updater kecil front-end yang tujuannya hanya memperbarui file dengan $ 1 jika tidak dikunci. Lockfiles diimplementasikan dengan memeriksa pada dasarnya apakah ada file tertentu (/var/run/yourscript.lck) dan jika ya, tunggu file tersebut menghilang untuk sementara waktu, dan gagal jika tidak. Anda juga harus menghapus file kunci ketika selesai memperbarui file.

Bersiaplah untuk menangani situasi di mana skrip tidak dapat memperbarui file karena file sedang sibuk.

LawrenceC
sumber
8
Trik: gunakan direktori alih-alih file untuk mengunci, karena mkdirberfungsi sebagai uji coba-dan-atom.
mattdm
1
Jika Anda ingin berbicara tentang penguncian, maka sebaiknya Anda menggunakanflock(2)
Ehtesh Choudhury
@mattdm Saya menemukan bahwa symlink ln -s dummy lockfile(bahkan jika rusak) dapat bekerja juga karena akan gagal jika symlink sudah ada. Saya ingin tahu beberapa cara untuk menguji apakah itu benar-benar 100% aman.
Aquarius Power
1

Ketika saya baru saja googled pertanyaan ini, saya mencoba untuk memecahkan masalah memperbarui keadaan (yaitu variabel shell) dari subkulit. Sehingga seseorang dapat menetapkan variabel, katakanlah, di dalam pipa - dan tugas akan terlihat transparan kepada induknya.

Tentu saja, ini tidak mungkin dengan cara sederhana karena setiap bagian dari pipa dieksekusi dalam subkulit, yang diambil forkdari shell induk dan karenanya memiliki memori yang merupakan tampilan copy-on-write pada memori induk. Namun, saya menduga bahwa solusi ramping dan transparan dapat dimungkinkan berdasarkan IPC " memori bersama " .

Dan saya bahkan menemukan implementasi dari desain ini ... tapi ada di Perl.

Menambahkan jawaban ini sebagai solusi yang memungkinkan.

ulidtko
sumber