`#!` Sözdiziminin davranışı neden POSIX tarafından belirtilmiyor?


17

Gönderen Shell Komut Dili POSIX şartnamenin sayfa:

Kabuk komutları dosyasının ilk satırı "#!" Karakterleriyle başlarsa, sonuçlar belirtilmez.

POSIX'in davranışı neden #!belirtilmedi? Bu kadar taşınabilir ve yaygın olarak kullanılan bir şeyin belirtilmemiş bir davranışa sahip olacağını şaşırtıcı buluyorum.


1
Standartlar, uygulamaları belirli davranışlara bağlamamak için belirtilmemiş şeyleri bırakır. Örneğin, "oturum açma", "Bir kullanıcının sisteme erişim kazanması için belirtilmeyen etkinlik" tir.
Kusalananda

2
POSIX yürütülebilir yolları belirtmediğinden, bir shebang hattı zaten doğal olarak taşınabilir değildir; Ne olursa olsun belirterek kazanacağımdan pek emin değilim.
Michael Homer

1
@MichaelHomer, kesinlikle değil mi? Standart, satırın, söz konusu yolun ne olması gerektiğini söylemeden bile yorumlayıcı için kullanılacak bir yol içerdiğini belirtebilir.
ilkkachu

1
@HaroldFischer Kabuk tarafından yorumlanmadığı sürece, ya işletim sistemi çekirdeği (en azından Linux'ta yapılır, bu desteği oluşturma süresi boyunca gerçekten devre dışı bırakabilir) veya exec()işlevi uygulayan herhangi bir kitaplık tarafından yorumlanır . Bu nedenle, çoklu mermilere karşı kontrol etmek size ne kadar taşınabilir olduğunu söylemez.
Austin Hemmelgarn

2
@HaroldFischer Ayrıca, POSIX uyumlu işletim sistemleri arasında bile davranış tutarlı değildir. Linux ve macOS farklı davranır: Linux, mekik çizgisini boşluklarla tam olarak tokenleştirmez. macOS kod yorumlayıcısının başka bir kod olmasına izin vermez. Ayrıca bakınız en.wikipedia.org/wiki/Shebang_(Unix)#Portability
jamesdlin

Yanıtlar:


21

Öncelikle düşünüyorum çünkü:

  • davranış uygulama arasında büyük farklılıklar gösterir. Tüm ayrıntılar için https://www.in-ulm.de/~mascheck/various/shebang/ adresine bakın .

    Ancak şimdi, en çok Unix benzeri uygulamaların minimum alt kümesini belirtebilir: #! *[^ ]+( +[^ ]+)?\nilk sözcüğün yerel bir yürütülebilir dosya için mutlak bir yol olduğu gibi (yalnızca bir veya iki kelimede taşınabilir dosya adı karakter kümesindeki karakterler ile) yürütülebilir dosya setuid / setgid ise belirtilmeyen çok uzun ve davranış belirtilmez ve uygulama, yorumlayıcı yolunun veya komut dosyası yolunun argv[0]yorumlayıcıya aktarılıp aktarılmadığını tanımlar .

  • POSIX, yürütülebilir dosyaların yolunu zaten belirtmiyor. Birçok sistem /bin/ içinde POSIX öncesi yardımcı programlara /usr/binsahiptir ve başka bir yerde POSIX yardımcı programlarına sahiptir ( /bin/shBourne kabuğunun olduğu ve POSIX'in bulunduğu Solaris 10'da olduğu gibi /usr/xpg4/bin; Solaris 11, daha POSIX uyumlu olan ksh93 ile değiştirdi, ancak çoğu araçlar /binhala eski POSIX olmayan araçlar ). Bazı sistemler POSIX sistemleri değildir, ancak POSIX modu / öykünmesi vardır. Tüm POSIX için gereken, bir sistemin POSIXly olarak davrandığı belgelenmiş bir ortam olmasıdır.

    Örneğin Windows + Cygwin'e bakın. Aslında, Windows + Cygwin ile, bir komut dosyası bir cygwin uygulaması tarafından çağrıldığında ancak yerel bir Windows uygulaması tarafından çağrılmadığında onurlandırılır.

    POSIX, shebang mekanizmasını belirtmiş olsa bile, POSIX sh/ sed/ awk... komut dosyaları yazmak için kullanılamaz (ayrıca, shebang mekanizmasının bir seçenek sonu geçmesine izin vermediği için güvenilir sed/ awkkomut dosyası yazmak için kullanılamayacağını unutmayın. işaretleyici).

Şimdi belirtilmemiş olması, onu kullanamayacağınız anlamına gelmez (iyi, #!sadece sıradan bir yorum olmasını ve bir patlama olmamasını beklerseniz ilk satırın başlamaması gerektiğini söylüyor ), ancak bu POSIX size garanti vermez.

Deneyimlerime göre, shebangs kullanmak, POSIX'in kabuk komut dosyaları yazma yöntemini kullanmaktan daha fazla taşınabilirlik garantisi verir: she-bang'ı bırakın, komut dosyasını POSIX shsözdiziminde yazın ve komut dosyasını her ne çağırırsa shüzerine POSIX uyumlu bir çağrı çağırmasını umuyoruz. betiğin doğru araçla doğru ortamda çağırılacağını biliyorsanız, aksi halde değil.

Bunun gibi şeyler yapmanız gerekebilir:

#! /bin/sh -
if : ^ false; then : fine, POSIX system by default
else
  # cover Solaris 10 or older. ": ^ false" returns false
  # in the Bourne shell as ^ is an alias for | there for
  # compatibility with the Thomson shell.
  PATH=`getconf PATH`:$PATH; export PATH
  exec /usr/xpg4/bin/sh - "$0" ${1+"$@"}
fi
# rest of script

Windows + Cygwin'e taşınabilir olmak istiyorsanız, dosyanızı bir .batveya .ps1uzantıyla adlandırmanız ve aynı dosya üzerinde cygwin'i çağırmak cmd.exeveya powershell.exeçağırmak için benzer bir numara kullanmanız gerekebilir sh.


İlginç bir şekilde, 5. sayıdan : "#! Yapısı bu uzantıyı sağlamak isteyen uygulamalar için ayrılmıştır. Taşınabilir bir uygulama kabuk komut dosyasının ilk satırı olarak #!
muru

muru Komut dosyası gerçekten taşınabilir olsaydı, POSIX çalıştıran gerçek bir POSIX sisteminde POSIX shtarafından yürütüleceği için bir hashbang satırına gerek yoktur sh.
Kusalananda

1
@Kusalananda bu sadece kullanılmışsa execlpveya execvpkullanılmışsa doğrudur , değil mi? Kullanacak olsaydım, execveENOEXEC ile sonuçlanır mıydı?
muru

9

[POS] davranışı tüm POSIX şikayet mermileri arasında tutarlı görünüyor. Burada kıpır kıpır oda ihtiyacını görmüyorum.

Yeterince derin görünmüyorsun.

1980'lerde bu mekanizma fiilen standardize edilmedi . Dennis Ritchie bunu uygulamasına rağmen, bu uygulama evrenin AT&T tarafında halka ulaşmamıştı. Etkin bir şekilde sadece halka açıktı ve BSD'de biliniyordu; çalıştırılabilir kabuk komut dosyalarıyla AT&T Unix'te bulunmaz. Dolayısıyla standardize etmek makul değildi. İşlerin durumu, bu çağdaş doco ile örneklenmiştir:

BSD ile başlayan dosyaların #! interpreterdoğrudan yürütülmesine izin verirken, SysV yalnızca a.out dosyalarının doğrudan yürütülmesine izin verir. Bu exec…(), bir BSD programındaki rutinlerden birinin bir örneğinin SysV altında /bin/shbu program için yorumlayıcıyı (tipik olarak ) yürütmek için değiştirilmesi gerekebileceği anlamına gelir .
- Stephen Frede (1988). Msgstr "Sistem X Sürüm Y'de Programlama". Avustralya Unix Sistemleri Kullanıcı Grubu Bülteni . Cilt 9. Sayı 4. s. 111.

Burada önemli bir nokta, kabuklara bakarken, yürütülebilir kabuk komut dosyalarının varlığı aslında exec…()fonksiyonlar için bir konudur . Kabuklar , bugün bile bazı kabuklarda bulunan (ve günümüzde fonksiyonların alt kümesi için zorunlu olan) yürütülebilir kod mekanizmasının öncüllerini içerir exec…p()ve biraz yanıltıcıdır. Bu bağlamda standardın ele alması gereken şey exec…(), yorumlanmış bir komut dosyasında nasıl çalıştığıdır ve POSIX'in ilk oluşturulduğu sırada, hedef işletim sistemleri spektrumunun büyük bir kısmında ilk etapta işe yaramadı .

Betik sözlü sihirli sayı mekanizması özellikle bu yana standardize edilmemiştir neden bir alt soru vardı evrenin AT & T tarafında kamuoyuna ulaştı ve dokümante edilmiş exec…()yılında Sistem 5 Arayüzü Tanımı ile açmak 1990'larda, :

Bir tercüman dosyası formun bir satırıyla başlar

#! yol adı [arg]
burada pathname yorumlayıcının yoludur ve arg isteğe bağlı bir argümandır. Bir execyorumlayıcı dosyası oluşturduğunuzda, sistem execbelirtilen yorumlayıcıdır.
- exec. Sistem V Arayüz Tanımı . Cilt 1. 1991.

Ne yazık ki, davranış bugün 1980'lerde olduğu gibi neredeyse tamamen farklıdır ve standartlaşmak için gerçekten yaygın bir davranış yoktur. Bazı Unices (örneğin, ünlü HP-UX ve FreeBSD) komut dosyalarını komut dosyaları için yorumlayıcı olarak desteklemez. İlk satırın boşlukla ayrılmış bir, iki veya birçok öğe olup olmadığı MacOS (ve 2005'ten önceki FreeBSD sürümleri) ve diğerleri arasında değişir. Desteklenen maksimum yol uzunluğu değişir. ve POSIX taşınabilir dosya adı karakter kümesinin dışındaki karakterler, baştaki ve sondaki boşluk gibi zor. 0., 1. ve 2. argümanların ortaya çıktığı şey de karmaşıktır ve sistemler arasında önemli farklılıklar vardır. Bazı anda POSIX conformant ama olmayan-Uixix sistemleri hala bu tür bir mekanizmayı desteklememektedir ve zorunlu kılmak, onları artık POSIX uyumlu olmaya dönüştürecektir.

daha fazla okuma


1

Diğer cevapların bazılarında belirtildiği gibi uygulamalar farklıdır. Bu, mevcut komut dosyalarıyla geriye dönük uyumluluğu standartlaştırmayı ve korumayı zorlaştırır . Bu, modern POSIX sistemleri için bile geçerlidir. Örneğin, Linux, mekik çizgisini boşluklarla tam olarak tokenleştirmez. macOS kod yorumlayıcısının başka bir kod olmasına izin vermez.

Ayrıca bkz. Http://en.wikipedia.org/wiki/Shebang_(Unix)#Taşınabilirlik

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.