“/ Bin / sh” “/ bin / bash” öğesini gösterdiğinde kabuk komut dosyası çalıştırma


11

Bu soruda aşağıdakileri okudum :

bash - POSIX uyumlu hale getiren bir --posix anahtarını destekler. Ayrıca sh olarak çağrılırsa POSIX'i taklit etmeye çalışır .

Yukarıdaki alıntı, /bin/shbunun bir bağlantı olduğunu varsayar /bin/bash.

Ama "sh olarak çağrıldı" ile ne kastedildiğini tam olarak anlamıyorum .


Diyelim ki "script.sh" olarak adlandırılan şu komut dosyası var:

#!/bin/bash
echo "Hello World"

Lütfen aşağıdaki durumların her birinde komut dosyasının normal bashmodda mı yoksa POSIX modunda mı çalışacağını söyleyin (çalışan bir terminalde aşağıdaki komutları yürüttüğümü varsayın bash):

  1. sh script.sh
  2. bash script.sh
  3. ./script.sh

Şimdi "script.sh" (yukarıdaki komut dosyası gibi ama shebang olmadan) adı verilen aşağıdaki komut dosyası olduğunu söyle:

echo "Hello World"

Lütfen aşağıdaki durumların her birinde komut dosyasının normal bashmodda mı yoksa POSIX modunda mı çalışacağını söyleyin (çalışan bir terminalde aşağıdaki komutları yürüttüğümü varsayın bash):

  1. sh script2.sh
  2. bash script2.sh
  3. ./script2.sh

Yanıtlar:


19

Yalnızca 1 ve 4 numaralı vakalar POSIX modunda çalışır ( shbaşka bir sh uygulaması değil, bash olduğu varsayılarak ). Açıkça basholmadan çağıran herhangi bir --posixdurum, mesele olsun ya da olmasın, olmayacaktır. Açıkça çağıran shher durum olur. Mesele sadece betik için zaten hiçbir kabuk başlatılmadığında kullanılır.

Durum 6, terminaliniz çalışıyorsa bash, POSIX modunda çalışmaz ve Bash, kendisini kullanarak çağırır. Terminal yerine zsh yayınlanırken, dava 6 olur da POSIX modunda çalıştırın. POSIX, bu durumda ne olması gerektiği konusunda belirsiz ve Bash ve zsh orada farklı seçimler yaptı. Bash betiği kendisini kullanarak çağırır, zsh kullanırsa sh(ne olursa olsun). Diğer mermiler de bu noktada değişir.


Hangi modda olduğunuzu söylemenin basit bir yolu komut dosyası gövdesini oluşturmaktır:

kill -SIGHUP

hangi olacak POSIX modunda bir hata ile başarısız , ama için kullanım talimatlarını vermek killbunun dışında. Bu kolay bir ayrımdır ve karşılaşabileceğiniz kadarıyla geriye giden uzun bir Bash versiyonları ile çalışır.


3
Ortam değişkeni veya bashgibi POSIX modunda çalışmaya zorlanacak başka şeyler de vardır . POSIXLY_CORRECTSHELLOPTS=posix
Stéphane Chazelas

1
[ -o posix ]bash'de posix modunda çalıştığınızı kontrol etmenin daha açık bir yoludur (diğer kabuklarda değil (yash hariç), bu yüzden bunu bir shkomut dosyasında yapmak istemezsiniz ). POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'çıkışlar yes`
Stéphane Chazelas

2
6 durumunda bash , POSIX'in gerektirdiği gibi POSIX modundayken betiği POSIX modunda kendisiyle çağırır . POSIX, she-bang mekanizmasını belirtmez ve 6, yürütülebilir komut dosyalarına sahip olmanın tek POSIX yoludur ve açıkça belirtilmiştir (POSIX ortamlarında, komut dosyasının uyumlu bir sh yardımcı programı tarafından yorumlanması amaçlanır).
Stéphane Chazelas

8

"Çağrıldı", Bash'i başlatan işlemin "sıfırıncı" komut satırı argümanına koyduğu her şeyi ifade eder argv[0].

Bir program exec*()syscalls ile başlatıldığında , programı içeren ikili dosyanın adını gerçekten bilmiyorlar, ancak bunun yerine çağrı işlemi oraya ne isterse koymakta özgürdür. Genellikle, elbette, isim dosya sisteminden alınır, bu yüzden çalıştırırsanız /bin/sh, oraya koyarsınız. Ve /bin/shBash ise , bir sembolik bağlantı olmak zorunda değildir, sert bir bağlantı veya kabuk programının başka bir kopyası olabilir.

"Program adı" ayarına bir örnek olarak, Bash'ın execkomutu -aseçenekle sıfırıncı argümanı ayarlayabilir . (Aynı şeyi Perl veya doğrudan C vb. İle de yapabiliriz.)

Burada, mynamesadece sıfırıncı argümanını bastıran basit bir C programı, gördüğü isim:

$ ./myname 
I am ./myname
$ (exec -a something ./myname )
I am something
$ mv ./myname somename
$ ln -s somename othername
$ ./somename 
I am ./somename
$ ./othername
I am ./othername

Kaynak:

#include <stdio.h>
int main(int argc, char *argv[]) {
    printf("I am %s\n", argv[0]);
    return 0;
}

Ancak, numaralı soruları cevaplamak için ...

Çalışan (1 & 4) sh somescriptne olursa olsun çalışır shsenin üzerindedir PATH, muhtemelen /bin/shama gibi muhtemelen bir şey/usr/xpg4/bin/sh .

  • Bash ise, adı gördüğü için POSIX modunda çalışır sh.
  • Z kabuğu veya Korn kabuğu ise, aynı şekilde adı görür sh, ancak Bourne kabuğu uyumlu olmayı amaçlayan ve bu kabukların her ikisinde de tam POSIX uyumluluk modundan farklı olan "SH uyumlu" modda çalışır. .
  • Elbette Almquist kabuğu, gerçek bir Bourne kabuğu veya başka bir şey olabilir.

(2 ve 5) Koşu bash somescriptdüzenli Bash modunda çalışacaktır (yine, elbette bashsizin ne olduğuna bağlı PATH.)

(3) Burada, komut dosyasının adı doğrudan program dosyası yerine sistem çağrısına verilir. Çekirdek, hashbang satırını okur ve komut dosyasını çalıştırmak için kullanır.

(6) Bu karmaşık olanı. (3) 'e benzer, ancak ENOEXEC (Exec format error)hashbang hattı olmadığından programı başlatmak için sistem çağrısı başarısız olur ( ). Bundan sonra ne olacak çalıştırmakta olduğu kabuk olup olmadığı sarkar kendisini POSIX modunda. POSIX, POSIX uyumlu bir kabuğun yanıt olarak belirli bir şekilde davranmasını gerektirir ENOEXEC. Bununla birlikte, "bir merminin çağrılmasına eşdeğer bir komut" da bazı farklılıklar vardır, bu da farklı mermilerin farklı şeyler yaptığı anlamına gelir.

  • Bourne Again kabuğu , komut dosyasının adıyla ilk komut satırı bağımsız değişkeni ile aynı modda yeniden çalışır . POSIX uyumlu modunda, elbette kendisini POSIX uyumlu modunda çalıştırır, böylece POSIX uyumlu bir kabuk çağırmak için POSIX gereksinimine uyar.
  • Z kabuğu, Almquist kabuğu ve Korn kabuğu /bin/sh, ilk komut satırı bağımsız değişkeni olarak diğer bağımsız değişkenlerin önüne eklenen komut dosyasının adıyla çalışır . Z kabuğu, Almquist kabuğu ve Korn kabuğu, /bin/shprogramın bir olduğunu varsayarak POSIX uyumlu bir kabuk çağırmaya çalışıyorlar .

Bu C programının kaynak kodunu paylaşabilir misiniz ..
GypsyCosmonaut

int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
Stig Hemmer

Hepsi bukadar.
ilkkachu

4

Yürütülen kabuk ya komut satırında ya da gövdede çağrılan kabuktur (komut satırı belirtmezse).

Yani, sürüm 1 ve 4 ile çalışacak shbash ile 2 ve 5 ve 6 olabilir değil etkileşimli sh kullanarak (ve bazı diğerleri), yayınlanmaya. Bash betiği başlatır. Ksh da. Zsh bunu sh olarak başlatır.

shBash bağlıysa, yalnızca olduğu gibi başlatılanlar posix seçeneğini kullanır /bin/sh.

Herhangi bir bash ksh veya zsh sürümünün çalışıp çalışmadığını tespit etmek için bu satırı komut dosyanıza ekleyin:

echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"
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.