Bash betiğinin başlığında, bu iki ifade arasındaki fark nedir:
#!/usr/bin/env bash#!/usr/bin/bash
env Man sayfasına danıştığımda şu tanımı alıyorum:
env - run a program in a modified environment
Bunun anlamı ne?
Bash betiğinin başlığında, bu iki ifade arasındaki fark nedir:
#!/usr/bin/env bash
#!/usr/bin/bash
env Man sayfasına danıştığımda şu tanımı alıyorum:
env - run a program in a modified environment
Bunun anlamı ne?
Yanıtlar:
Bir komut through Koşu /usr/bin/envprogramı varsayılan sürümü mevcut ne varsa arayan yararı vardır env ironment.
Bu şekilde, sistemdeki belirli bir yerde aramak zorunda kalmazsınız, çünkü bu yollar farklı sistemlerde farklı yerlerde olabilir. Yolunda olduğu sürece onu bulacak.
Tek dezavantajı, /usr/bin/env awk -fLinux'u desteklemek istiyorsanız birden fazla argümanı (örneğin yazamayacaksınız ) geçemeyeceğinizdir , çünkü POSIX satırın nasıl yorumlanacağı konusunda belirsizdir ve Linux ilkinden sonra her şeyi yorumlar tek bir argümanı belirtmek için boşluk. Bu /usr/bin/env -Ssorunun envüstesinden gelmek için bazı sürümlerinde kullanabilirsiniz , ancak komut dosyası daha az taşınabilir hale gelecek ve oldukça yeni sistemlere zarar verecektir (örneğin, daha sonra değilse Ubuntu 16.04 bile).
Başka bir dezavantajı, açık bir yürütülebilir dosya çağırmamanızdan dolayı, hata potansiyeli ve çok kullanıcılı sistemlerin güvenlik sorunları ( bashörneğin, yürütülebilir dosyalarınızı yolunuza çağırmayı başarmışsa ).
#!/usr/bin/env bash #lends you some flexibility on different systems
#!/usr/bin/bash #gives you explicit control on a given system of what executable is called
Bazı durumlarda, birincisi tercih edilebilir (çalıştırılabilir satırın yeniden çalışmasına gerek kalmadan, python'un birden çok sürümüyle python betikleri çalıştırmak gibi). Ancak güvenliğin odaklandığı durumlarda, kod enjeksiyon olanaklarını sınırladığı için ikincisi tercih edilecektir.
#!/usr/bin/env echo Helloyakınır: /usr/bin/env: echo Hello: No such file or directory. Görünüşe göre echo Hellotek bir argüman olarak davranıyor /usr/bin/env.
envKomut kesinlikle argümanların komuta iletilmesine izin verir. Sorun #!satırın anlambilimidir ve bu çekirdeğe bağlıdır. Son Linux çekirdekleri böyle şeylere izin verir #!/usr/bin/env command args, ancak eski Linux çekirdekleri ve diğer sistemler buna izin vermez.
Kullanarak #!/usr/bin/env NAME$ PATH ortam değişkenindeki NAME öğesinin ilk eşleşmesi için kabuk araması yapar. Mutlak yolun farkında değilseniz veya aramak istemiyorsanız yararlı olabilir.
Tercümanın yolunu açık olarak tanımlamak yerine /usr/bin/bash/, env komutunu kullanarak, tercüman aranır ve ilk bulunduğu yerden başlatılır. Bu hem yukarı hem de aşağı yönlü
Kabuk komut ile başlarsanız #!/bin/bash, hep birlikte çalışacak bashdan /bin. Onlar ancak başlarsanız #!/usr/bin/env bash, onlar arayacaktır bashiçinde $PATHve sonra da bulabilirsiniz ilkinden başlar.
Bu neden faydalı olabilir? bashBash 4.x veya daha bashyeni bir sürüm gerektiren komut dosyalarını çalıştırmak istediğinizi varsayalım , ancak sisteminizde yalnızca 3.x yüklü ve şu anda dağıtımınız daha yeni bir sürüm sunmuyor veya yönetici değilseniz ve bu sistemde yüklü olanı değiştiremezsiniz .
Tabii ki, bash kaynak kodunu indirebilir ve ~/binörneğin kendi bash'ınızı sıfırdan oluşturabilirsiniz. Ve ayrıca değiştirebilir $PATHsenin içinde değişken .bash_profiledahil etmek dosyanın ~/binilk girişi (aynı PATH=$HOME/bin:$PATHşekilde ~genişleyecek olmaz $PATH). Şimdi ararsanız bash, kabuk ilk önce $PATHsırayla arayacaktır , bu yüzden ile ~/binnerede bulacağınızla başlar bash. Komut dosyaları bashkullanmak için arama yaparsa aynı şey olur #!/usr/bin/env bash, bu nedenle bu komut dosyaları artık özel bashderlemenizi kullanarak sisteminizde çalışır .
Bunun bir dezavantajı, bunun beklenmedik davranışlara yol açabilmesidir, örneğin aynı makinedeki aynı komut dosyası, farklı ortamlar veya farklı arama yolları olan kullanıcılar için farklı yorumlayıcılarla çalışarak her türlü baş ağrısına neden olabilir.
En büyük dezavantajı env, bazı sistemlerin sadece bir argümana izin vereceğidir, bu yüzden #!/usr/bin/env <interpreter> <arg>sistemler <interpreter> <arg>tek bir argüman olarak göreceğinden (ifade alıntılanmış gibi davranacak) ve böylece envadlı bir tercüman arayacaktır <interpreter> <arg>. Bu envkomutun her zaman birden fazla parametrenin geçmesine izin veren bir sorun değil , hatta aramadan önce bu hattı ayrıştıran sistemin shebang ayrıştırıcısı ile ilgili bir sorun olduğunu unutmayın env. Bu arada bu çoğu sistemde düzeltildi, ancak betiğiniz ultra taşınabilir olmak istiyorsa, bunun çalıştıracağınız sistemde düzeltildiğine güvenemezsiniz.
Örneğin sudo, çevreyi temizleyecek şekilde yapılandırılmamışsa veya temizlenmemesi $PATHdışında da güvenlik etkileri olabilir . Bunu göstereyim:
Genellikle /biniyi korunan bir yer, sadece rootorada herhangi bir şeyi değiştirebilir. Ancak ana dizininiz çalıştırdığınız herhangi bir programda değişiklik yapamaz. Bu, kötü amaçlı kodun bashgizli bir dizine sahte yerleştirilebileceği .bash_profile, dizininizi o dizine ekleyecek şekilde değiştirebileceğiniz anlamına gelir $PATH, böylece kullanılan tüm komut dosyaları #!/usr/bin/env bashbu sahte ile çalışacaktır bash. Eğer sudotutarsa $PATH, başınız büyük belada.
Örneğin, bir aracın ~/.evil/bashaşağıdaki içeriğe sahip bir dosya oluşturduğunu düşünün :
#!/bin/bash
if [ $EUID -eq 0 ]; then
echo "All your base are belong to us..."
# We are root - do whatever you want to do
fi
/bin/bash "$@"
Basit bir komut dosyası yapalım sample.sh:
#!/usr/bin/env bash
echo "Hello World"
Kavram kanıtı ( sudosakladığı bir sistemde $PATH):
$ ./sample.sh
Hello World
$ sudo ./sample.sh
Hello World
$ export PATH="$HOME/.evil:$PATH"
$ ./sample.sh
Hello World
$ sudo ./sample.sh
All your base are belong to us...
Hello World
Genellikle klasik mermilerin hepsi yer almalıdır /binve bunları herhangi bir nedenden dolayı oraya yerleştirmek istemiyorsanız /bin, gerçek konumlarına işaret eden bir işaret eklemek (veya belki /binde bir işaret bağlantısıdır), bu yüzden Her zaman #!/bin/shve ile giderdim #!/bin/bash. Artık işe yaramazsa kırılacak çok fazla şey var. POSIX bu konumu gerektirmez (POSIX yol adlarını standartlaştırmaz ve bu nedenle shebang özelliğini hiç standartlaştırmaz), ancak çok yaygındır, bir sistem sunmasa bile /bin/sh, muhtemelen hala anlardı #!/bin/shve bununla ne yapılacağını bilir ve yalnızca mevcut kodla uyumluluk için olabilir.
Ancak Perl, PHP, Python veya Ruby gibi daha modern, standart olmayan, isteğe bağlı tercümanlar için, bulunmaları gereken hiçbir yerde belirtilmemiş. Bunlar olabilir /usr/binama onlar da olabilir /usr/local/binveya tamamen farklı bir hiyerarşi dalı (içinde /opt/..., /Applications/...vs.). Bu yüzden bunlar genellikle #!/usr/bin/env xxxshebang sözdizimini kullanır.
Yararlı buluyorum, çünkü env hakkında bilmediğimde, senaryo yazmaya başlamadan önce bunu yapıyordum:
type nodejs > scriptname.js #or any other environment
ve sonra dosyadaki satırı değiştirerek değiştiriyordum.
Bunu yapıyordum, çünkü bilgisayarımda nodejs nerede olduğunu hatırlamıyordum - / usr / bin / veya / bin /, bu yüzden benim enviçin çok faydalı. Belki bununla ilgili ayrıntılar var, ama bu benim nedenim