Bir tercümana bir yol belirtmek yerine, tercümanın adını taşıyan ve kabuğun $ PATH üzerinden bulmasını sağlayan bir Shebang olması mümkün mü?
Değilse, bunun bir nedeni var mı?
Bir tercümana bir yol belirtmek yerine, tercümanın adını taşıyan ve kabuğun $ PATH üzerinden bulmasını sağlayan bir Shebang olması mümkün mü?
Değilse, bunun bir nedeni var mı?
Yanıtlar:
PATH araması, genel olarak ortam değişkenleri gibi, kullanıcı alanındaki standart C kütüphanesinin bir özelliğidir. Çekirdek, arayandan execve
yeni sürece geçiş yaptığı bir ortam dışında ortam değişkenlerini görmez .
Çekirdek, yolda execve
( execvp
PATH araması yapmak gibi sarıcı işlevlere bağlıdır ) veya bir shebang'da ( execve
çağrıyı içten aşağı yukarı yönlendiren) herhangi bir yorum yapmaz . Bu yüzden mutlak yolu shebang put'a koymanız gerekiyor. Orijinal shebang uygulaması sadece birkaç kod satırları oldu ve önemli ölçüde beri genişletildi edilmemiştir.
Unix'in ilk sürümlerinde, kabuk, bir komut dosyasını çağırdığınızı fark ettiğinde kendisini başlatma işini yaptı. Shebang, birkaç nedenden dolayı çekirdeğe eklendi ( Dennis Ritchie'nin gerekçesini özetleyerek :
Yolsuz shebang'lar, çekirdeğin ortam değişkenlerine ve işlemine erişmesi için artırılmasını PATH
veya çekirdeğin PATH aramasını yapan bir kullanıcı alanı programını yürütmesini gerektirir. İlk yöntem, çekirdeğe orantısız miktarda karmaşıklık eklenmesini gerektirir. İkinci yöntem bir #!/usr/bin/env
shebang ile zaten mümkün .
Relative Göreceli bir yol koyarsanız, göreceli olarak işlemin geçerli dizinine (betiği içeren dizin değil) yorumlanır.
execve
, shebang'da mutlak bir yol gerektirmez , ancak bir shebang'da bağıl bir yola sahip olmak çok az mantıklıdır.
/lib64/ld-linux-x86-64.so.2
( ldd
çıktıya bakınız ). Linux bunu tamamen genel yapar: binfmt
destek (2.1.43'ten beri) tercüman yolu / büyü numarası veya dosya uzantısı çiftlerini kaydetmenizi sağlar. Bunları çalıştırdığınızda PE32 .exe
lerin çağrılmasını wine
, Java sınıfının ve jar dosyalarını çağırmanın java
, vb. Vb.
Göze göründüğünden daha fazlası var. #!
çizgiler Unix veya Linux çekirdeği tarafından yorumlanır #!
, kabukları bir yönü değildir. Bu PATH
, çekirdeğin neyi yürüteceğine karar verdiği sırada gerçekten bulunmadığı anlamına gelir .
Hangi çalıştırılabilir dosyayı çalıştıracağınızı veya perl
taşınabilir şekilde veya benzer şekilde çağrı yapmayı bilmemekle uğraşmanın en yaygın yolu kullanmaktır #!/usr/bin/env perl
. /usr/bin/env
Bir PATH
ortam değişkenini miras alan çekirdek çalıştırır . env
(bu örnekte) buluntular perl
olarak PATH
kullanır ve execve(2)
sistem çağrıyı çalıştırmak için çekirdek almak için perl
çalıştırılabilir.
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0
Tam yola dönüşüm kabuk tarafından yapılır (daha genel: Kullanıcı alanında). Çekirdek, doğrudan erişebileceği bir dosya adı / yolu bekler.
Sistemin PATH değişkenine bakarak yürütülebilir dosyasını bulmasını istiyorsanız, shebang'ınızı olarak yeniden yazabilirsiniz #!/usr/bin/env EXEC
.
Ancak bu durumda da aramayı yapan çekirdek değil.
strace
dönüştürülmüş /usr/bin/strace
) çalışıyor.