Shebang betiği çalıştıran kabuğu belirler mi?


84

Bu aptalca bir soru olabilir, ama hala soruyorum. Bir Shebang ilan etmiş olsaydım

#!/bin/bash 

başında my_shell_script.shbash kullanarak her zaman bu betiği çağırmam gerekir mi?

[my@comp]$bash my_shell_script.sh

veya örneğin kullanabilir miyim

[my@comp]$sh my_shell_script.sh

ve betiğim shebang kullanarak çalışan kabuğu belirler? Aynı kshkabukta oluyor mu? AIX kullanıyorum.


6
senin tarafında küçük bir karışıklık var: "_some_shell some_script" yaptığınızda _some_shell başlar ve some_script'i yorumlamasını ister. Yani hayır, eğer "sh my_shell_script.sh" yaparsanız shebang'ı yorumlamaz, fakat betiği sh olarak yorumlayacaktır. Shebang'ı kullanmak için: chmod +x my_shell_script.sh ; /path/to/my_shell_script.sh # or ./my_shell_script.sh if you happen to be in its directory
Olivier Dulac

Yanıtlar:


117

Shebang #! bir an insan okunabilir örneğidir sihirli sayı bayt dize oluşan 0x23 0x21tarafından kullanılır, exec()yürütülecek dosyası bir komut dosyası veya bir ikili olup olmadığını belirlemek için fonksiyonların ailesi. Shebang mevcut olduğunda, shebang'dan exec()sonra belirtilen yürütülebilir dosyayı çalıştıracaktır.

Bunun , soruda verilen her iki durumda da olduğu gibi komut satırında tercümanı belirterek bir komut dosyası çağırmanız durumunda, komut satırında exec()belirtilen tercümanı çalıştıracağını, komut dosyasına bile bakmayacağını unutmayın.

Bu nedenle, diğerlerinin de belirttiği gibi, exec()shebang satırında belirtilen tercümanı çağırmak istiyorsanız , komut dosyasının çalıştırılabilir bit'i ayarlaması ve çalıştırması gerekir ./my_shell_script.sh.

Davranış aşağıdaki komut dosyası ile gösterilmesi kolaydır:

#!/bin/ksh
readlink /proc/$$/exe

Açıklama:

  • #!/bin/kshkshTercüman olmayı tanımlar .

  • $$ Geçerli işlemin PID değerini tutar.

  • /proc/pid/exe işlemin yürütülebilirine bir bağlantı (en azından Linux'ta; AIX üzerinde, /proc/$$/object/a.out, yürütülebilir dosyaya bir bağlantıdır).

  • readlink sembolik bağlantının değerini gösterecektir.

Örnek:

Not : Varsayılan kabuk Ubuntu, bu gösteren ediyorum /bin/shsembolik köprü ise karalamak ie /bin/dashve /bin/kshbir sembolik olduğunu /etc/alternatives/kshsırayla sembolik köprü ise, /bin/pdksh.

$ chmod +x getshell.sh
$ ./getshell.sh 
/bin/pdksh
$ bash getshell.sh 
/bin/bash
$ sh getshell.sh 
/bin/dash

Bu cevap için teşekkürler Thomas. Senaryoyu Node.js veya Java'dan bir alt süreç olarak başlatıyormuşuz gibi yapın. Bir "exec" işlemi başlatabilir miyiz ve daha sonra exec kabuk betiğini çalıştıracak mı? Beause'a soruyorum bu sorunun cevaplarını arıyorum: stackoverflow.com/questions/41067872/…
Alexander Mills

1
@AlexanderMills Bu cevapta exec()bahsedilen bir sistem çağrısıdır, komut execbir kabuk yerleşiktir, bu yüzden Node.js veya Java'dan bir exec programı çağıramazsınız . Bununla birlikte, örneğin Runtime.exec()Java tarafından çağrılan herhangi bir kabuk komutu sonunda exec()sistem çağrısı tarafından işlenir .
Thomas Nyman,

Ha, evet ben) (alt düzey exec çağırmak için bir yol olup olmadığını merak nasılsa node.js gelen çağrı sadece belirtilen Java API ile indeede aşinayım
Alexander Mills

@AlexanderMills hayal ediyorum ki child_process.{exec(),execFile(),spawn()} hepsi C exec()(ile process) kullanılarak uygulanacaktı .
Thomas Nyman,

10

Evet öyle. Bu arada saçma bir soru değil. Cevabım için bir referans burada . Bir Komut Dosyasını Başlatma #!

  • Buna bir shebang veya "bang" satırı denir.

  • Bash tercümanına giden mutlak yoldan başka bir şey değil.

  • Bir sayı işaretinden ve bir ünlem işareti karakterinden (#!) Oluşur, bunu / bin / bash gibi yorumlayıcının tam yolundan izler.

    Linux altındaki tüm komut dosyaları ilk satırda belirtilen tercümanı kullanarak çalıştırılır Neredeyse tüm bash komut dosyaları genellikle #! / Bin / bash (Bash'in / bin içine yüklendiğini varsayarak) ile başlar. Bu, Bash'in komut dosyasını yorumlamak için kullanılmasını sağlar başka bir kabuk altında yürütülürse. Shebang, Bell Laboratuvarlarında Versiyon 7 Unix ve 8 arasında Dennis Ritchie tarafından tanıtıldı. Daha sonra Berkeley'deki BSD hattına da eklendi.

Bir Tercüman Çizgisini Yok Sayma (shebang)

Bir tercüman satırı belirtmezseniz, varsayılan değer genellikle / bin / sh'dir. Ancak #! / Bin / bash satırını ayarlamanız önerilir.


3
Çekirdek, ayrıntılı bir şekilde, yalnızca statik olarak bağlı ikili dosyaların nasıl çalıştırılacağını ve başkaları için tercüman bilgisinin nerede bulunacağını bilir (ikili dosyadaki özel bir alan veya Shebang hattı). Genellikle bir kabuk betiğinin yürütülmesi, kabuktaki shebang satırını takip etmek ve daha sonra da kabuk ikilisindeki DT_INTERP alanını dinamik bağlayıcıya izlemek anlamına gelir.
Simon Richter

5
Ayrıca bunun kabuk komut dosyalarıyla sınırlı olmadığını unutmayın. Tüm metin tabanlı komut dosyaları bunu kullanır. Örneğin #!/usr/bin/perl #!/usr/local/bin/python #!/usr/local/bin/ruby, birden fazla sistemi desteklemek için kullanılan diğer bir yaygın shebang girişi, kullanmak istediğiniz tercümanı bulmak için env kullanmaktır, like#!/usr/bin/env perl #!/usr/bin/env python
sambler

@ sambler'dan bahsetmişken env, hangisi tercih edilmeli? Python ve Perl sıklıkla kullanılır env, kabuk komut dosyalarında, bu genellikle ihmal edilir ve shebang söz konusu kabuğa işaret eder.
polemon

1
@polemon daha az tercih edilir ve daha fazla hangi yollar üzerinde değişir. Temel kabuklar tüm sistemlerde aynı yoldadır. Perl ve python'un güncel sürümleri farklı sistemlerde farklı konumlara yerleştirilebilir, böylece env kullanımı aynı shebang'ın her zaman çalışmasına izin verir, bu yüzden env, kabuk komut dosyalarından ziyade perl ve python komut dosyalarında daha çok kullanılır.
Sambler,

env$ PATH bir program bulmak için biraz kesmek olduğunu. Adından da anlaşılacağı gibi ortam değişkenlerini ayarlamaz. $ PATH farklı kullanıcılar için farklı bir sonuç olabilir. Ancak, betiklerin tuhaf bir yere makul bir perl yorumlayıcısı yerleştiren sistemlerde değişiklik yapılmadan çalışmasına yardımcı olur.
John Mahowald

4

execLinux çekirdeğinin sistem çağrısı (shebangs anlar #!yerel)

Bash yaparken:

./something

Linux'ta, bu execsistem çağrısı yolu ile çağırır ./something.

Çekirdeğin bu satırı iletilen dosyaya çağrılır exec: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

Dosyanın ilk baytlarını okur ve karşılaştırır #!.

Karşılaştırma doğruysa, satırın geri kalanı Linux çekirdeği tarafından ayrıştırılır; bu , ilk bağımsız değişken olarak execpath /usr/bin/env pythonve current dosyasıyla başka bir çağrı yapar :

/usr/bin/env python /path/to/script.py

ve bu #, yorum karakteri olarak kullanılan herhangi bir komut dosyası dili için işe yarar .

Ve evet, ile sonsuz bir döngü yapabilirsiniz:

printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

Bash hatayı tanır:

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#! sadece insan tarafından okunabilir olur, ancak bu gerekli değildir.

Dosya farklı baytlarla execbaşlarsa , sistem çağrısı farklı bir işleyici kullanır. Diğer en önemli dahili işleyici ELF çalıştırılabilir dosyalar için geçerli: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 bayt kontrolü yaptığı 7f 45 4c 46aynı zamanda insan olur ki ( için okunabilir .ELF). /bin/lsELF çalıştırılabilir olan ilk 4 baytı okuyarak onaylayalım :

head -c 4 "$(which ls)" | hd 

çıktı:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

Böylece, çekirdek bu baytları gördüğünde, ELF dosyasını alır, doğru şekilde belleğe koyar ve onunla yeni bir işlem başlatır. Ayrıca bakınız: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861

Sonunda, kendi Shebang işleyicilerini binfmt_miscmekanizma ile ekleyebilirsin . Örneğin, dosyalar için özel bir işleyici.jar ekleyebilirsiniz . Bu mekanizma, dosya uzantısına göre işleyicileri bile destekler. Başka bir uygulama, farklı bir mimarinin yürütülebilirlerini şeffaf bir şekilde QEMU ile çalıştırmaktır .

Ancak POSIX'in shebangları belirttiğini sanmıyorum:: ps ps ps ps ps htt ps ps ps: https://unix.stackexchange.com/a/346214/32558 , gerekçeli bölümlerde ve çalıştırılabilir komut dosyaları sistem tarafından destekleniyorsa olabilir ".


1
./somethingBir kabuktan koşmak tam yolu geçmez exec, fakat girilen tam yoldur. Cevabında bunu düzeltebilir misin? Do echo "$0"betiğinizdeki ve bu durumda göreceksiniz.
AndiDog

2

Aslında, sonuç olarak alırsanız, shebang satırında belirtilen çalıştırılabilir, sadece çalıştırılabilirdir. Bazı metin yorumlayıcılarını çalıştırılabilir olarak kullanmak mantıklıdır, ancak gerekli değildir. Sadece açıklama ve gösteri için oldukça işe yaramaz bir test yaptım:

#!/bin/cat
useless text
more useless text
still more useless text

Dosya metin.txt Adlandırılan ve exectuable biraz set chmod u+x test.txtsonra "sözde",: ./test.txt. Beklendiği gibi, dosyanın içeriği çıktı. Bu durumda, kedi shebang hattını görmezden gelmez. Sadece tüm satırları verir. Herhangi bir faydalı tercüman bu nedenle bu Shebang hattını görmezden gelebilmelidir. Bash, perl ve PHP için, sadece bir yorum satırıdır. Yani evet, bunlar shebang hattını görmezden geliyorlar.


-1

Topladığım kadarıyla ne zaman bir dosya çalıştırılabilir bir bit kümesi varsa ve çağrıldığında, çekirdek nasıl ilerleyeceğini belirlemek için dosya başlığını analiz eder (bildiğim kadarıyla LKM'ler üzerinden özel dosya biçimleri için özel işleyiciler ekleyebilirsiniz). Dosya # ile bir metin dosyası gibi görünüyorsa! başlangıcında bir araya getirme işlemi, aynı satırda söz konusu shebang'dan hemen sonra belirtilmesi gereken bir yol olan başka bir çalıştırılabilir dosyaya (genellikle bir tür kabuk) gönderilir. Daha sonra çekirdek, kabuğu çalıştırmaya ve dosyayı işlemesi için geçirmeye devam eder.

Kısacası, betiği hangi kabukla çalıştırdığınızın bir önemi yoktur - çekirdek yürütmeyi uygun olana her iki şekilde de gönderir.


4
bash ./myscript.shVe arasında belirgin bir fark var ./myscript.sh.
bir CVn

Bu "belirgin fark" derken ne demek istiyorsun?
jrara,

3
@jrara Cevabımı bakın, "betiği hangi kabukla çalıştırdığın önemli değil" ifadesinin doğru olmadığıdır.
Thomas Nyman,
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.