Shebang'ı / bin / bash yerine / bin / sh ile işaretlemenin bir nedeni var mı?


53

Gördüğüm çoğu kabuk senaryosunda (kendim yazmadıklarım dışında), Shebang’ın kurulduğunu fark ettim #!/bin/sh. Bu beni daha eski senaryolarda şaşırtmadı, ama oldukça yeni senaryolarda da var.

Tercih edilmesinin bir sebebi var mı /bin/shüzerinde /bin/bashberi, bashbir on yıl içinde geri iyi gidiyor birçok Linux ve BSD makinelerde, hemen hemen her yerde ve genellikle varsayılan?


23
/bin/shBelirli bashişlevleri kullanmazsanız kullanmak iyi bir seçimdir . Bir gün senaryonuzdan birini kurulu olmadığı bir sistemde kullanmak zorunda kalabilirsiniz (uzak sunucu, katıştırılmış bilgisayar ...)
Mathieu

1
Genel olarak, kendi düşüncelerine dayanan cevaplara kendilerini ödünç veren sorular sormaktan kaçınmalısınız (bu sorunun cevaplanabileceğine inanmamın tek yolu bu - ama bu sadece benim düşüncem ) .
mikeserv

9
Bu soruyu, sadece birkaç yıl boyunca bu konuyu ele alan en az iki kuruma işaret ederek, tarihe ve sonuca bakarak, sadece bir fikir olmadan yanıtlamanın mümkün olduğuna inanıyorum. Daha fazla okuma için ekli, önyükleme. ☺
JdeBP

3
@JulesMazur ...the answers so far are fairly subjective..."Subjektif" bir ifade, tanım gereği kanaatine dayanmaktadır. /bin/bashsadece açıkça bash gerektiğinde kullanılmalıdır. Bir geliştirici olarak 40 yıldan uzun bir süre önce, uzun zaman önce bash, testler dışında neredeyse hiçbir zaman açıkça ihtiyacım olmadı . (Kabuk uzantılarını engellemek için de çaba sarf ediyorum, ancak komut dosyalarımın çoğu dağıtım amaçlı.) Ağdaki birçok komut dosyası da geniş kullanım için tasarlanmalı.
user2338816

2
@ user2338816 benim kötü, amaç demek . Puanınız için teşekkürler!
Jules

Yanıtlar:


83
  1. Varsayılan olarak bash göndermeyen sistemler vardır (örneğin FreeBSD).
  2. Bash yüklü olsa bile, içinde bulunmayabilir /bin.
  3. Çoğu basit komut dosyası bash gerektirmez.
  4. POSIX kabuğunu kullanmak daha portatiftir ve scriptler çok çeşitli sistemlerde çalışacaktır.

17
Başka bir neden: sık sık / bin / sh bash'den daha hızlıdır veya en azından daha hızlı yüklenir (daha küçük olması nedeniyle).
derobert

5
@derobert, /bin/sho değilse hızlıdır bashhala OS / X veya RHEL gibi birkaç sistem vardır, /bin/sholduğunu bash.
Stéphane Chazelas

1
Hayır. Bazı işletim sistemleri bağlantı kurar, çünkü bash geriye doğru uyumludur.
Sobrique

7
Epeyce komut varsayalım /bin/sholduğunu /bin/bash. Geçiş Ubuntu bash için çizgi hepsini kırdı.
atamanroman

19
@atamanroman: Her şeyden önce senaryolar yanlıştı, #!/bin/bashBash'i isterlerse kullanmaları gerekirdi (yanlış bir şey yok!). Değişiklik çoğunlukla Debian'da gerçekleşti. Kullanıcı deneyimini geliştirdi, sistemin başlangıç ​​zamanı üzerinde ölçülebilir bir etkisi oldu. Aynı zamanda güvenliği de olumlu yönde etkiledi, "Shellshock" bölümüne bakın.
Dietrich Epp

28

Linux'taki çoğu sistem komut dosyası (Debian ile ilgili: Ubuntu, Mint, vb.) Linux, bu sistemlerdeki varsayılan / bin / sh olan daha hızlı bir çizgide çalışacak şekilde yazılmıştır. Sebep iki yönlüdür:

  • Sistemin hızı. Daha küçük bir çizgi kodu daha hızlı yüklenir ve daha hızlı çalışır. Bazı (küçük?) Kabuk komut programcıları için ek çaba (maliyet) ile.

  • Güvenlik. Kabuk çeşitliliğine sahip olmak, böceklere karşı dayanıklılığı arttırır. Debian sistemleri çoğunlukla kabuğa karşı savunmasızdı, çünkü varsayılan kabuk böyle bir kırılganlığa sahip değildi.

Bash gerçekten de kullanıcılar için varsayılan kabuktur , çünkü daha güçlüdür ve kodlamayı kolaylaştırmak için daha fazla öğeye sahiptir. Ayrıca shMac OS'de de varsayılandır (/ bin / sh ile bağlanan). Ancak, bashlink ismiyle çağırmak shposix uyumlu bir kabuk olarak başlatılmasını sağlar.


2
Daha basit bir kabuğun daha sınırlı mevcut araçları seti, kod yazmayı daha zor hale getirir (lütfen bununla ilgili fanatik savaşlardan kaçının). Bu yüzden bazı kullanıcılar bassh'dan bile daha fazla el aleti olan zsh gibi. Her iki uç arasında bir denge olduğu gibi Bash'i daha çok seviyorum.

4
@RobertL, ksh ile eklenen ve bash tarafından benimsenen tesislerin birçoğu vardır çünkü bunlar sağlam ve doğru senaryolar yazma sürecini büyük ölçüde kolaylaştırır. Örneğin dolaylı ödev ve değerlendirmenin güvenli bir şekilde yapılmasına izin veren çeşitli ilaveler olmadan, bir kişi kendini evalgüvenlik görevlisine maruz bırakarak bulabilir ; benzer şekilde, yerleşik regex desteği olmadan, tek bir satırda bile eşleştirmek için harici komutları (ağır performans cezalarında) kullanmanız gerekebilir, vb.
Charles Duffy

1
@RuiFRibeiro, Debian'da hiçbir şey statik olarak bağlantılı değildir. Çizgi daha sınırlıdır, ancak komut dosyaları için daha hızlı olması için temel olarak etkileşimli özelliklerde (tamamlanma ve benzeri) sınırlıdır.
Jan Hudec

21

Diğerleri ise, Bourne Again kabuğunun varsayılan ve her yerde olduğu gibi düpedüz yanlış olduğu sorusunun öncüllerine dikkat çekti.

Buna ek olarak, kabuk komut dosyalarını yorumlamak için Bourne Again kabuğundan başka bir şeyi kullanmanın gerçekten iyi nedenleri vardır. Bu nedenler, Ubuntu ve Debian'ın büyük projesini birkaç yıl boyunca temel ilkeleri kaldırmak ve sistemin başlatılması ( Sistem 5 ile çok fazla sayıda kabuk betiği idi rc) ve paket yükleme / kaldırma işlemlerinin çalıştırdığı kabuk betiğini yapmak için birkaç yıl boyunca motive etti. Debian Almquist yerine Bourne Again kabuğu.

Basitçe söylemek gerekirse: Bourne Again kabuğu, olduğu gibi etkileşimli özelliklerle dolu bir POSIX uyumlu kabuk betiği için en hızlı kabuk yorumlayıcısı değildir. Eğer biri kişinin kabuk komutlarını POSIX uyumlu hale getirebilirse, onları Debian Almquist kabuğu gibi daha hafif bir programla yorumlayarak birinin sistemi daha iyi performans gösterecektir. (Sonunda Debian, Almquist kabuğuna hafifçe ayarlamalar yapmak zorunda kaldı, basitçe derinden ve geniş bir şekilde gömülü olan ve kurtulmak için çok faydalı olan birkaç POSIX dışı kabuk yapısı için destek ekledi.)

Tüm bunların sonucu bootstrap performansında büyük bir kazanç oldu.

Dolayısıyla, dikkate alınması gereken iki farklı kabuk sınıfı vardır:

  • Hesap veritabanındaki kullanıcılar için etkileşimli oturum açma kabukları olarak yapılandırılmış gösterişli etkileşimli özelliklerin bulunduğu kabukları .
  • Kabuk komut programları tarafından komut dosyası yorumlayıcıları olarak kullanılan çok sayıda komut dosyasını hızlı bir şekilde yorumlayan kabuklar .

Bu konuda “tercih etmek /bin/sh” olarak konuşmanın aşırı basitleştirici olduğuna dikkat edin. Debian'ın aslında en az iki hedefi vardı :

  1. Debian Almquist kabuğunu, Z Kabuğunu (POSIX modunda), Bourne Again kabuğunu (POSIX modunda), MirBSD Korn kabuğunu ve diğerlerini kullanan yöneticilerin karşısında /bin/sh

    1. … Senaryoları mümkün olduğunca taşınabilir hale getirmek, böylece /bin/shharitalanan şeyleri bir şeylere bölmemek; veya

    2. … Taşınabilir olmayan komut dosyalarını hazırlamak , yalnızca o haritayı beklemek yerine açık bir şekilde doğru tercüman programını hedefler /bin/sh.

  2. Debian Almquist için varsayılan eşleme kabuk yapma yoktu /bin/sh, yerine Bourne Shell bu komut böylece vardı POSIX conformant (veya daha doğru bir Debian Politikası Manuel conformant) daha çabuk koştu.

Ve elbette biri bu konuya girdiğinde, çok daha fazlasını alabilir; Kabuk betiklerinin veya derlenmiş programların beğenilme /bin/trueve bunlara ilişkin takasların değerlendirilmesi /usr/bin/clear. Ancak bu neyse ki bu cevabın kapsamı dışında. ☺

Bunların hiçbiri elbette çok yeni, hatta Unix'e özgü değil. Yüzyılın başından önce, hem "etkileşimli" hem de "etkileşimli olmayan" tatlarda gelen, docodaki bu ayrımı açıklayan COMSPECve OS2_SHELLçevre değişkenleri arasındaki farkı belirten bir komut satırı tercümanı yazdım ve yayınladım . Benzer şekilde, Debian'ın System V içindeki temelleri kaldırma rcve paket yükleme / kaldırma komut dosyalarının tartışılması 1990'lı yıllara dayanmaktadır.

daha fazla okuma


2
“Sonunda Debian, Almquist kabuğuna ufak ayarlamalar yapmak zorunda kaldı, derinden ve geniş ölçüde gömülü ve kurtulmak için çok faydalı olan birkaç POSIX dışı kabuk yapısı için destek sağladı.” - Bağlantılarından hangisinin bu konuda bilgisi var? Bu çok ilginç geliyor. :)
Wildcard

3
IMHO, performans, insanların değişikliklerle aynı fikirde olmasını sağlamak için sadece bir motivasyondur. Değişimin ilk büyük nedeni, bash'ın geriye dönük uyumluluğu kırmaya devam etmesiydi. Şahsen kariyerimde bash problemlerini en az 3 kez düzeltmek zorunda kaldım, çünkü senaryo bash'ın bir versiyonunda çalışacak fakat başka bir konuda başarısız olmuş (genellikle işletim sistemi güncellemesinden sonra olur). Dash sadece biraz daha hızlı bir tercüman değildir. Aynı zamanda davranış açısından çok daha kararlıdır.
Slebetman

Schily Bourne ShellMan sayfasındaki yorumların, bkz. Schilytools.sourceforge.net/bosh.html , insanların taşınabilir bir komut dosyası nasıl yazdıklarını anlamalarına izin vermek için uygun olup olmadıklarıyla ilgilenirim (yalnızca Bourne Shell features1989'dan itibaren). Yaptığım, eski Bourne Kabuklarında olmayan her geliştirmeden bahsetmek oldu. BTW: Ayrıca, çizgi halinde bir temel bilgiler listesi bilmekle de ilgileniyorum.
schily

8

Shebang'ı / bin / bash yerine / bin / sh ile işaretlemenin bir nedeni var mı?

Evet. @ Marco'nun mükemmel cevabı bu konuyu özetliyor.

Shebang'ımda ne kullanmalıyım?

Kendi senaryolarınızı yazarken, shebang'ı test ettiğiniz en genel şeye yöneltmelisiniz.

Benim sistemimde (Centos 6.6), shşöyle bağlanmıştır bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Bu #!/bin/bash, senaryomda bashims olmadığını doğrulamadığım sürece her zaman shebang'ımda kullandığım anlamına gelir .

Shebang'ı ayarlayarak, #!/bin/shsenaryonun tüm uygulamaları ile çalışacağına dair söz veriyorsun sh.

Bu, senaryonun bash ile çalışacağını söylemekten çok daha büyük bir söz.

shSistemin hangi uygulamayı kullandığına bağlı olarak yanlış davranacak bir betik örneği :

#!/bin/sh
n=1
a=$((++n))
echo $n

bashKomut dosyasını kullanırken yazdıracak:

2

dashKomut dosyasını kullanırken yazdıracak:

1

Kullanmak istersem #!/bin/shne yapmam gerekir?

  • Komut dosyasını şu şekilde kontrol edin checkbashisms- Bunun tüm bashimleri bulamayacağını unutmayın. Yukarıdaki senaryomda faşizm bulamadı
  • Komut dosyasını başka bir shuygulama kullanarak test edin . Tipik olarak test ediyorum dash, ancak bazı temel bilgiler veya göstergelerin hala geçebileceğini umuyorum.

DashAsBinSh sayfa Ubuntu wiki ilginç birçok bilgi vardır.


6
“Senaryolarını yazarken, shebang'ı test ettiğin en genel şeye yönlendirmelisin ... Shebang'ı #! / Bin / sh olarak ayarlayarak, senaryonun tüm sh uygulamaları ile çalışacağına söz veriyorsun. ." Mükemmel nokta +1, ve bana gelecek için çobanlarımı nasıl yazacağımı yeniden düşündün. Teşekkür ederim! :)
Wildcard

2
Peki, tüm uygulamaları değil /bin/sh; sadece POSIX uyumlu olanları.
Blacklight Shining

4

Daha güçlü ve ergonomik bir dilde bir betik yerine bir kabuk betiği yazmak için geriye kalan tek neden, bilinmeyen bir yüklü yazılım setine sahip eski sistemlere taşınabilirliğin diğer etkenlerden daha önemli olduğudur .

/bin/shUnix adında her şeyde kullanılabilen tek ve tek komut dosyası tercümanıdır. Ancak çok sayıda eski sistemde /bin/shve ilgili yardımcı programlar POSIX.1-1996 "kabuk ve yardımcı programlar" özelliğiyle bile uyumlu değil, daha modern bir şey olsun. Standart uyumlu araçlar isteğe bağlı bir eklentidir, /usr/xpg4açık bir yere monte edilmiş veya böyle bir konumda bulunur. 1 Taşınabilir altküme kabuk diline komut dosyası yazmak POSIX kabuk diline komut dosyası kullanmaktan bile daha sıkıcı ve hataya açıktır. ( configureBana inanmıyorsanız , bir Autoconf tarafından oluşturulan komut dosyasını okuyun . Sadece kurulum sizi ikna etmek için yeterli olacaktır.)

Ancak, başka bir kod tercümanın kurulu olduğunu varsayabilirsiniz (örneğin Bash), daha iyi bir betik dili için tercüman yüklendiğini varsayabilirsiniz . Mesela Perl, Bash'in olduğundan daha muhtemel.

Bu nedenle, asla bir #! /bin/bashsenaryo yazmamalısınız, çünkü eğer bu bir seçenekse, daha iyi bir dil de bir seçenektir.

1 Örneğin, Solaris 10 ve üstü, orijinal Bourne kabuğunu olduğu gibi göndermiştir/bin/sh . Solaris 11'in onu ksh93 olarak güncellediğini biliyorum.


3
Sistemi başlatmak için hangi dilde bir senaryo yazacaksınız? Veya bir SOHO yönlendirici içinde (sınırlı embebed sistemler)? Veya Android'de? Bütün bu durumlarda bir kabuk bulunacaktır. Perl değil.

1
Yanıtınızın Solaris ile ilgili bölümleriyle ilgili bazı yanlışlıklar var. Solaris 10 ve üstü günü, /bin/shbir değil POSIX.1-1996 ama aslında önceden POSIX sözdizimi orijinal Bourne kabuğu. Bu, #!/bin/shsenaryoların bu sürümlerle çalıştırılması için çok zayıf bir shebang yapar . Solaris'teki taşınabilir komut dosyaları, #!/usr/xpg4/bin/shdiğer işletim sistemlerinde çok taşınabilir olmayacaktı. En son Solaris'te, 2011'de ilk kez piyasaya sürülen Oracle Solaris 11, /bin/shen ksh93son POSIX özelliklerine uyan bir modern ve birçok modern uzantıya sahip.
jlliagre

1
@BinaryZebra: "Bir kabuk" olacak, evet. Ancak, bash mutlaka kabuk değildir (özellikle de çoğu SOHO yönlendiricisinin ashmeşgul kutusu ile birlikte kullanıldığı) kullanır ve zwol'ün perl'in bashtan daha yaygın olduğunu doğru bulmaya eğilimli olduğunu düşünüyorum.
Ben Voigt,

1
@BenVoigt Bu cümleye yorum yapıyorum "Bir kabuk betiği yazmak için kalan tek neden". Hala bazı görevler için bir kabuk gerektiren bazı örnekler vardır (hepsi değil). Bunlar kafamın tepesinden örneklerdi. OTOH Yeterli hafızalı (hemen hemen tümü standart) sistemlerde ve Perl (veya Python veya ....) kurulumlarında yeterli güç oldukça hızlı ve kolaydır. Ancak, belirli bir kabuğun savunuculuğunu yapmıyorum. Bunu benim yorumumda nerede okuyorsun?

2
"Eğer varsa bash, o zaman daha iyi bir dildir, böylece herhangi bir bashkod yazmamalısınız" diyen yüksek görüşlü ve dürüst olmayan iddiasına tamamen katılmıyorum . Ayrıca, @sixtyfootersdude'nin işaret ettiği gibi, betiğinizin herhangi bir POSIX kabuğu ile çalıştığını test etmediğiniz sürece her zaman kullanmanız gerekir . #!/bin/bash
Joker

0

Aslında ikisini de kullanıyor olmalısın.

#! /bin/env sh

veya

#! /bin/env bash

bu şekilde, her iki kabuğu da bu sisteme yüklendikleri için çağırırsınız.

Süper güvenli olmak için ( örneğin , tek kullanıcılı yeniden başlatma durumlarında) shaksi takdirde kullanın bash.


6
Gönderen Bu yanıt : the advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH. The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.Bu, muhtemelen de geçerlidir shve bash.
Jules

12
Hayır, #!/bin/envtaşınabilir bir komut dosyasında hiçbir şey kullanmamalısınız . /bin/shVarolduğunu ve çalışan, POSIX uyumlu bir kabuk olduğunu varsaymak tamamen mantıklıdır . Öte yandan, hiçbir sistemimde yok /bin/env.
Blacklight Shining

Aynı zamanda iyi bir nokta.
Jules

1
@Blacklight Shining, içinde POSIX uyumlu bir kabuk olduğunu varsaymak kesinlikle yanlıştır /bin/sh. POSIX bunu gerektirmez ve POSIX uyumlu bir platformda POSIX uyumlu bir ortam elde etmek için diğer kuralları tanımlar.
schily

4
/usr/bin/envevrensel olarak mevcut değil ...
vonbrand
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.