Unix'te başka bir sürecin ortam değişkenlerini değiştirmenin bir yolu var mı?


105

Unix'te, bir işlemin diğerinin ortam değişkenlerini değiştirmesinin herhangi bir yolu var mı (hepsinin aynı kullanıcı tarafından çalıştırıldığı varsayılarak)? Genel bir çözüm en iyisidir, ancak değilse, birinin diğerinin çocuğu olduğu özel durum ne olacak?

Düzenleme: gdb ile nasıl olur?


Bu beni çirkin olmaktan çok etkiliyor. Çözmek istediğiniz asıl sorun nedir?
Jens

1
Örnek: Kullanıcı arayüzü tarafından başlatılan her yeni uygulamanın alabilmesi için bir ortam değişkeni tanımlamak istiyorum. Başlangıç ​​betiklerinden birinde ve RE-LOGIN'de değişkenleri tanımlamak dışında herhangi bir yöntem bilmiyorum. Bununla birlikte, yeniden oturum açmak istemiyorum, ancak yalnızca mevcut oturumdaki değişkenleri tanımlayarak yeni uygulamaların onu alabilmesi için - UI oturumunu kapatmadan.
AlikElzin-kilaka

Yanıtlar:


143

Gdb aracılığıyla:

(gdb) attach process_id

(gdb) call putenv ("env_var_name=env_var_value")

(gdb) detach

Bu oldukça çirkin bir hack ve elbette sadece bir hata ayıklama senaryosu bağlamında yapılmalıdır.


8
Öyleyse bu, sürece GDB'nin yaptığı gibi bağlanırsanız ve sonra ayrılırsanız bir sürecin ortamını gerçekten değiştirebileceğiniz anlamına geliyor gibi görünüyor. Görünüşe göre sadece bunu yapan bir program yazmak mümkün olacak.
yas

3
"Sadece bunu yapan bir program yazmak mümkün görünüyor" Gerçekten .. öyle.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

2
Cygwin kullanılarak derlenmeyen işlemler için, cygwin kullanan Windows üzerinde bile çalışır!
Juan Carlos Muñoz

12
Bunun yalnızca işlem, önceki bir getenv'den sonra değeri kalıcı olarak önbelleğe almamışsa işe yarar.
An̲̳̳drew

2
Bazı sistemlerde gdb şu hatayı verebilir 'putenv' has unknown return type; cast the call to its declared return type:; bu gibi durumlarda putenvaramayı şu şekilde değiştirmelisiniz :call (int) putenv ("env_var_name=env_var_value")
Emir Üner

22

Muhtemelen teknik olarak yapabilirsiniz (diğer cevaplara bakın), ancak size yardımcı olmayabilir.

Çoğu program, ortam değişkenlerinin başlangıçtan sonra dışarıdan değiştirilemeyeceğini bekler, bu nedenle çoğu muhtemelen başlangıçta ilgilendikleri değişkenleri okuyacak ve buna göre başlatılacaktır. Bu yüzden daha sonra onları değiştirmek bir fark yaratmayacaktır çünkü program onları asla tekrar okumayacaktır.

Bunu somut bir sorun olarak yayınladıysanız, muhtemelen farklı bir yaklaşım izlemelisiniz. Sadece meraktan olsaydı: Güzel soru :-).


1
Yararlı olacağı en yaygın kullanım durumu, alt süreçlerin yeni ortam değişkenlerini devralmasını sağlamaktır, örneğin, yeni terminallerin yeni değişkenleri kullanmasını istediğiniz masaüstü ortamında.
Hjulle

13

Esasen hayır. Yeterli ayrıcalığa sahipseniz (kök veya oradaki) ve / dev / kmem (çekirdek belleği) etrafında dolaştıysanız ve işlemin ortamında değişiklikler yaptıysanız ve süreç daha sonra ortam değişkenine gerçekten yeniden referans verdiyse (yani süreç env var'ın bir kopyasını henüz almamıştı ve sadece bu kopyayı kullanmıyordu), o zaman belki, eğer şanslı ve zekiysen ve rüzgar doğru yönde esiyorsa ve ayın evresi doğruysa, belki, bir şeyler başarabilirsin.


2
Cevabı alamadım.
AlikElzin-kilaka

@kilaka: Anahtar kelime ikincidir - Hayır . Cevabın geri kalanı, kök ayrıcalıklarına sahipseniz veya bir hata ayıklayıcı çalıştırıyorsanız, o zaman bunu yapabilirsiniz, ancak tüm pratik amaçlar için cevabın Hayır olduğunu söylüyor .
Jonathan Leffler

Çalışan bir kabuk betiğiniz var; Kabuk betiğinizin üst sürecindeki ortamı değiştirmek istersiniz ... böylece kabuk betiği gdbüst süreçte başlar ve değişikliği yapmak için komut dosyası oluşturulur ve üst süreci çökertmeden çalışır. Tamam - muhtemelen yapabilirsin, ama bu rutin olarak yapacağın bir şey değil. Pratik amaçlar için, bu nedenle, cevap Hayır olarak kalır . Cevabın geri kalanı teorik olarak mümkün olan, biraz pratik olmayan bir şekilde yapılabilir alternatifleri kapsar.
Jonathan Leffler

7

Jerry Peek'ten alıntı:

Eski bir köpeğe yeni numaralar öğretemezsin.

Yapabileceğiniz tek şey, başlatmadan önce çocuk sürecin ortam değişkenini değiştirmektir : üzgünüm, üst ortamın kopyasını alır.

Ayrıntılar için http://www.unix.com.ua/orelly/unix/upt/ch06_02.htm adresine bakın.

/ Proc kullanımı hakkındaki cevaba bir yorum. Linux altında / proc değil iş, sen gelmez, desteklenen ancak olamaz değiştirmek /proc/${pid}/environkök bile, dosyayı: Bu edilir kesinlikle salt okunur.


Geriye şu soruyu bırakan soru: env var değerleri gerçekte nerede depolanır? Bu çekirdek tarafından mı yapılır? Yoksa kabuk değerleri depoluyor mu ve / proc / <pid> / environ bunları oradan alıyor mu?
oliver

Bu bir uygulama detayıdır ve (ayrı) iyi bir soru olabilir. Sanırım her UNIX, depolama için kendi yöntemini kullanıyor, ancak bunların tümü, özelliklerin bir parçası olan yukarıda açıklanan davranışı paylaşıyor.
Davide

7

Bunu yapmanın oldukça uydurma bir yolunu düşünebilirdim ve bu keyfi süreçler için işe yaramayacak.

'Char * getenv' kullanan kendi paylaşımlı kitaplığınızı yazdığınızı varsayalım. Ardından, 'LD_PRELOAD' veya 'LD_LIBRARY_PATH' env ayarını yaparsınız. vars, böylece her iki işleminiz de paylaşılan kitaplığınız önceden yüklenmiş olarak çalıştırılır.

Bu şekilde, aslında 'getenv' işlevinin kodu üzerinde bir kontrole sahip olacaksınız. Sonra her türden iğrenç numara yapabilirsin. "Getenv" parametreniz, env değişkenlerinin alternatif değerleri için harici yapılandırma dosyasına veya SHM segmentine başvurabilir. Veya istenen değerlerde regexp arama / değiştirme yapabilirsiniz. Veya ...

Bunu, dinamik bağlayıcıyı (ld-linux.so) yeniden yazmak yerine rastgele çalışan süreçler için (kök olsanız bile) yapmanın kolay bir yolunu düşünemiyorum.


Bu yapılabilir olmalıdır. Var = değer çiftleri için küçük bir gdbm veritabanınız olabilir. Malloc
dstromberg

Yine de bu yöntemin önceden düşünülmesi gerektiğini düşünüyorum. Yanlışlıkla çok fazla işleme uygulamamaya da dikkat etmelisiniz.
dstromberg

3

Veya yeni işlem için bir yapılandırma dosyasını güncelleme sürecinizi alın ve ardından şunlardan birini yapın:

  • güncellenmiş yapılandırma dosyasını yeniden okumak için yeni işlemde bir kill -HUP gerçekleştirin veya
  • işlemin yapılandırma dosyasını ara sıra güncellemeler için kontrol etmesini sağlayın. Değişiklikler bulunursa, yapılandırma dosyasını yeniden okuyun.

2

Bildiğim kadarıyla değil. Gerçekten, IPC yöntemlerinden (paylaşılan bellek, semaforlar, soketler vb.) Birini gerektiren bir işlemden diğerine iletişim kurmaya çalışıyorsunuz. Bu yöntemlerden biriyle veri aldıktan sonra, ortam değişkenlerini ayarlayabilir veya diğer işlemleri daha doğrudan gerçekleştirebilirsiniz.


1

Unix'iniz / proc dosya sistemini destekliyorsa, env'i OKUMAK çok önemlidir - bu şekilde sahip olduğunuz herhangi bir sürecin ortamı, komut satırını ve diğer birçok özelliğini okuyabilirsiniz. Değiştiriyorum ... Bir yolunu düşünebilirim, ama bu KÖTÜ bir fikir.

Daha genel durum ... Bilmiyorum, ama taşınabilir bir cevap olduğundan şüpheliyim.

(Düzenlendi: Orijinal cevabım, OP'nin ortamı değiştirmek değil, OKUMAK istediğini varsayıyordu)


Ooops, cevabımı düzenledim - envanteri değiştirmek değil okumak istediğini varsayıyordum.
Mike G.

1
Beni asılı bırakma. Senin kötü fikrin nedir?
raldi

Linux'ta, sahip olduğunuz diğer işlemler için / proc / <pid> / mem okuma-yazmayı açabileceğinizi düşünüyorum ... Yine de emin değilim. Denemek ve aslında çevreyle uğraşmak KESİNLİKLE kötü bir fikir olur. Bu yüzden denemenizi
Mike G.

1

UNIX, süreçler arası iletişimle doludur. Hedef örneğinizde bazılarının olup olmadığını kontrol edin. Dbus, "masaüstü" IPC'de standart hale geliyor.

Awesome -client kullanarak Awesome pencere yöneticisinin içindeki ortam değişkenlerini lua kodunun bir Dbus "göndereni" ile değiştiriyorum.


1

Doğrudan bir cevap değil ama ... Raymond Chen'in bunun etrafında [Windows tabanlı] bir mantığı vardı ancak geçen gün :

... Bunu yapmanın kesinlikle desteklenmeyen yolları veya bir hata ayıklayıcının yardımıyla çalışan yollar olmasına rağmen, başka bir işlemin komut satırına programlı erişim için desteklenen hiçbir şey yoktur, en azından çekirdek tarafından sağlanan hiçbir şey yoktur. ...

İhtiyaç duymadığınız bilgileri takip etmeme ilkesinin bir sonucu olmamasıdır. Çekirdeğin başka bir işlemin komut satırını almasına gerek yoktur. İşleve aktarılan komut satırını alır CreateProcessve onu, GetCommandLineişlevin onu alabileceği bir konumda başlatılan işlemin adres alanına kopyalar . İşlem kendi komut satırına eriştiğinde, çekirdeğin sorumlulukları tamamlanmış olur.

Komut satırı işlemin adres alanına kopyalandığından, işlem komut satırını tutan belleğe bile yazabilir ve onu değiştirebilir. Böyle bir durumda, orijinal komut satırı sonsuza kadar kaybolur; bilinen tek kopyanın üzerine yazılmıştır.

Başka bir deyişle, bu tür herhangi bir çekirdek tesisi,

  • uygulaması zor
  • potansiyel olarak bir güvenlik sorunu

Bununla birlikte, en olası neden, böyle bir tesis için sınırlı kullanım durumlarının olmasıdır.


1

Görünüşe göre putenv şu anda çalışmıyor , ama setenv çalışıyor . Mevcut kabuktaki değişkeni başarılı bir şekilde ayarlamaya çalışırken kabul edilen cevabı test ediyordum

$] sudo gdb -p $$
(gdb) call putenv("TEST=1234")
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x0
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=

ve nasıl çalıştığı değişkeni:

$] sudo gdb -p $$
(gdb) call (int) setenv("TEST", "1234", 1)
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x55f19ff5edc0 "1234"
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=1234
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.