Neden tüm komut dosyaları şu şekilde başlıyor?
#!/bin/sh
veya ile
#!/bin/csh
Bu gerekli mi? Bunun amacı nedir? Ve ikisi arasındaki fark nedir?
Neden tüm komut dosyaları şu şekilde başlıyor?
#!/bin/sh
veya ile
#!/bin/csh
Bu gerekli mi? Bunun amacı nedir? Ve ikisi arasındaki fark nedir?
Yanıtlar:
Bu şu şekilde bilinir Shebang
:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#! yorumlayıcı [isteğe bağlı-arg]
Bir shebang, yalnızca bir komut dosyasının yürütme iznine sahip olması durumunda geçerlidir (örneğin, chmod u + x script.sh).
Bir kabuk betiği çalıştırdığında, belirtilen yorumlayıcıyı kullanır.
Misal:
#!/bin/bash
# file: foo.sh
echo 1
$ chmod u+x foo.sh
$ ./foo.sh
1
#!
Çizgi (özellikle, uygulanması çekirdek söyler execve
bu program tercüme edilmiş bir dilde yazılmış olması sistem çağrısı); izleyen mutlak yol adı yorumlayıcıyı tanımlar. Makine koduna derlenen programlar, çoğu modern Unix'te 7f 45 4c 46
( ^?ELF) onları bu şekilde tanımlayan farklı bir bayt dizisi ile başlar .
Sen mutlak bir yol koyabilirsiniz istediğiniz herhangi bir program sonrasında #!
sürece bu program değil kendisi olduğu gibi, #!
komut dosyası. Çekirdek, bir çağrıyı yeniden yazar.
./script arg1 arg2 arg3 ...
nerede ./script
, ile başlar demek, #! /usr/bin/perl
komut satırı aslında olmuştu sanki
/usr/bin/perl ./script arg1 arg2 arg3
Ya da gördüğünüz #! /bin/sh
gibi yorumlanması amaçlanan bir senaryo yazmak için kullanabilirsiniz sh
.
#!
Eğer hat sadece işlenir doğrudan (komut dosyası çağırmak ./script
komut satırında); dosya da çalıştırılabilir olmalıdır ( chmod +x script
). Bunu yaparsanız sh ./script
, #!
satır gerekli değildir (ve varsa yok sayılacaktır) ve dosyanın çalıştırılabilir olması gerekmez. Nokta özelliğinin onlar yazılır hangi dili bilmek zorunda kalmadan yorumlanır dil programlarına çağırmak doğrudan sizi sağlamaktır. (Do grep '^#!' /usr/bin/*
- Sen pek çok stok programları bu özelliği kullanarak aslında olduklarını keşfedecek.)
İşte bu özelliği kullanmak için bazı kurallar:
#!
İlk iki olmalıdır bayt dosyasında. Özellikle, dosya gerekir (örneğin UTF-8 çalışacaktır ancak UTF-16 will not) ASCII uyumlu kodlama olması ve olmamalıdır bir "bayt sırası işareti" ile başlar, ya da çekirdek a olarak tanımayacaktır #!
senaryo.#!
mutlak bir yol olmalıdır (ile başlar /
). Boşluk, sekme veya yeni satır karakterleri içeremez.#!
ve /
. Oraya birden fazla boşluk koymayın.#!
satıra koyamazsınız , genişletilmezler.#! /usr/bin/awk -f
), bazen sadece yararlıdır ( #! /usr/bin/perl -Tw
). Ne yazık ki, mutlak yoldan sonra iki veya daha fazla argüman koyamazsınız .#! /usr/bin/env interpreter
bunun yerine kullanmanı söyleyecektir #! /absolute/path/to/interpreter
. Bu neredeyse her zaman bir hatadır. Programınızın davranışını $PATH
, komut dosyasını çalıştıran kullanıcının değişkenine bağlı kılar . Ve tüm sistemler env
ilk etapta sahip değildir .setuid
veya setgid
ayrıcalıklara sahip programlar kullanamaz #!
; makine koduna derlenmeleri gerekir. (Ne olduğunu bilmiyorsanız setuid
endişelenmeyin.)İlgili csh
, bu ilgilidir sh
kabaca Nutrimat olarak Gelişmiş Çay Yedek çaya yapar. Etkileşimli kullanıma göre sh
bir dizi avantajı vardır (ya da daha doğrusu; modern uygulamaları yakalamıştır) sh
, ancak tcsh
komut dosyası oluşturmak için onu (veya onun neslini ) kullanmak neredeyse her zaman bir hatadır . Genel olarak kabuk komut dosyası oluşturma konusunda yeniyseniz, bunu görmezden gelmenizi ve odaklanmanızı şiddetle tavsiye ederim sh
. csh
Giriş kabuğunuz olarak bir akraba kullanıyorsanız , bash
veya seçeneğine geçin zsh
, böylece etkileşimli komut dili öğrenmekte olduğunuz komut dosyası diliyle aynı olacaktır.
#!
; bunun iyi bir tarz olup olmadığı hakkında yorum yok. Bkz bu soruyu ve benim cevap artılarını ve eksilerini bir tartışma için #!/usr/bin/env
hack.
#!/usr/bin/env
Doğru Şeyin olduğu bir durumla karşılaştım , ancak bana kalırsa bunun neredeyse her zaman kötü bir fikir olduğu.
Bu, komut dosyanızı yorumlamak / çalıştırmak için hangi kabuğu (komut yorumlayıcısı) kullandığınızı tanımlar. Her kabuk, kullanıcıyla etkileşim kurma ve komut dosyalarını (programları) çalıştırma biçiminde biraz farklıdır.
Unix komut istemine bir komut yazdığınızda, kabuk ile etkileşime girersiniz.
Örneğin, #!/bin/csh
C kabuğunu, /bin/tcsh
t kabuğunu, /bin/bash
bash kabuğunu vb. İfade eder.
Hangi etkileşimli kabuğu kullandığınızı anlayabilirsiniz.
echo $SHELL
komut veya alternatif olarak
env | grep -i shell
Komut kabuğunuzu komut ile değiştirebilirsiniz chsh
.
Her birinin biraz farklı bir komut seti ve değişken atama yöntemi ve kendi programlama yapıları vardır. Örneğin, bash ile if-else ifadesi C-kabuğundakinden farklı görünüyor.
Bu sayfa , bash ve tcsh komutları / sözdizimi arasında "çeviri yaptığı" için ilgi çekici olabilir.
Yönergeyi kabuk betiğinde kullanmak, programları farklı bir kabuk kullanarak çalıştırmanıza izin verir. Örneğin, tcsh
kabuğu etkileşimli olarak kullanıyorum, ancak genellikle betik dosyasında / bin / bash kullanarak bash betikleri çalıştırıyorum.
Kenara:
Bu kavram diğer senaryolara da uzanıyor. Örneğin, Python'da program yapıyorsanız
#!/usr/bin/python
Python programınızın en üstünde
#! $SHELL
? Bu, Shebang'a doğru kabuğu koyar mı?
!#/bin/bash
direktifin güzelliği . Sisteme, kabuk betiğinizi çalıştırmak için hangi kabuğun kullanılacağını söyler.
$SHELL
o anda hangi mermiyi çalıştırdığınızı size söylemesine gerek yoktur; normalde size varsayılan kabuğunuzu söyler . tcsh setleri $version
ve $tcsh
; bash setleri $BASH_VERSION
. Tüm mermilerin benzer mekanizmaları olması gerekmez.
#!
Satır, komut dosyasını çalıştıran kişi tarafından kullanılan etkileşimli kabukla değil , komut dosyasının sözdizimiyle eşleşmelidir .
#!/bin/csh -f
; bu-f
, kabuğa kullanıcının kaynağını oluşturmamasını söyler.login
ve.cshrc
bu da komut dosyasının daha hızlı çalışmasını sağlar ve kullanıcının kurulumuna olan bağımlılıkları önler. (Daha da iyisi, csh betikleri yazmayın.)-f
Sh veya bash betikleri için kullanmayın ; aynı anlama sahip değil.