Dosya, sistem tarafından tanınan yürütülebilir dosya türlerinden biri olmadığından ve bu dosyayı yürütme izniniz olduğunu varsayarsak, execve()
sistem çağrısı genellikle ENOEXEC
( yürütülebilir değil ) hatasıyla başarısız olur .
O zaman ne olacak komutu çalıştırmak için kullanılan uygulama ve / veya kütüphane fonksiyonudur.
Bu bir kabuk, execlp()
/ execvp()
libc işlevi olabilir.
Diğer uygulamaların çoğu, bir komut çalıştırdıklarında bunlardan birini kullanır. Örneğin system("command line")
, genellikle sh
komut satırını (yolu derleme zamanında belirlenebilen ( Solaris'te /bin/sh
vs gibi /usr/xpg4/bin/sh
)) ayrıştırmaya çalışacak olan libc işlevi aracılığıyla bir kabuk çağıracaklar veya $SHELL
kendi başlarına depolanan kabukları çağıracaklar. vi
onun ile !
komuta veya xterm -e 'command line'
ve diğer birçok komutları ( su user -c
kullanıcının giriş kabuğu yerine çağıracağı $SHELL
).
Genel olarak, başlamamış, sessiz bir metin dosyası #
bir sh
komut dosyası olarak kabul edilir . Hangi sh
olsa değişecektir.
execlp()
/ execvp()
, execve()
döndükten ENOEXEC
sonra genellikle sh
onu çağırır . sh
Birden fazla standarda uygun olabildikleri için birden fazla standarda sahip sistemler sh
için tipik olarak derleme zamanında belirlenecektir (uygulamanın farklı bir yola işaret eden farklı bir kod bloğunu kullanarak execvp()
/ execlp()
bağlayarak sh
). Örneğin, Solaris'te bu /usr/xpg4/bin/sh
(standart, POSIX sh
) veya /bin/sh
(Solaris 10 ve daha eski sürümlerde Bourne kabuğu (antika kabuk), Solaris 11'de ksh93) olacaktır.
Mermiler söz konusu olduğunda, çok fazla varyasyon var. bash
AT & T ksh
(sürece bir alt işleminde, Bourne Kabuk tipik olarak komut kendilerini yorumlayacaktır exec
kullanılmıştır), bir simüle sonra execve()
tüm unexported değişkenler ayarlanmadan olduğu,,,, her yakın-on-exec fds kapalı tüm özel tuzakları çıkarıldı takma adlar, işlevler ... ( bash
komut dosyasını sh
modda yorumlar). yash
(kendini çalıştırır sh
olarak argv[0]
öylesine de sh
bunu yorumlamak mod).
zsh
, pdksh
, ash
Merkezli kabukları tipik olarak çağırır sh
(derleme zamanında olan tespit yol).
İçin csh
ve tcsh
(ve sh
bazı erken BSD türevi), dosyanın ilk karakteri ise #
, o zaman kendileri yorumlamak, ve çalıştırır sh
aksi. Bu yorum olarak csh
tanıdı #
ama Bourne kabuğu değil, bir shebang öncesi zaman geri gider , bu yüzden #
bir csh komut dosyası olduğunu bir ipucu oldu.
fish
(en azından sürüm 2.4.0), execve()
başarısız olursa bir hata döndürür (komut dosyası olarak ele almaya çalışmaz).
Bazı kabuklar ( bash
AT&T veya AT&T gibi ksh
) ilk önce sezgisel olarak dosyanın bir komut dosyası olup olmadığını belirlemeye çalışır. Yani, ilk birkaç baytta bir NUL karakteri varsa, bazı kabukların bir komut dosyasını çalıştırmayı reddedeceğini görebilirsiniz.
Ayrıca execve()
, ENOEXEC ile başarısız olursa, ancak dosyanın bir shebang hattı varsa, bazı kabukların bu shebang hattının kendilerini yorumlamaya çalıştığını unutmayın.
Birkaç örnek:
- Ne zaman
$SHELL
olduğunu /bin/bash
, xterm -e 'myscript with args'
olacak myscript
tarafından yorumlanır bash
içinde sh
mod. İle birlikte xterm -e myscript with args
, xterm
kullanacak execvp()
böylece script tarafından yorumlanacaktır sh
.
su -c myscript
Solaris 10 üzerinde nerede root
bireyin giriş kabuğu /bin/sh
ve /bin/sh
Bourne kabuğu olacak olan myscript
Bourne kabuk tarafından yorumlanır.
/usr/xpg4/bin/awk 'BEGIN{system("myscript")'
Solaris 10 üzerinde yorumlayacaktır /usr/xpg4/bin/sh
(aynı /usr/xpg4/bin/env myscript
).
find . -prune -exec myscript {} \;
Solaris 10'da (kullanma execvp()
) POSIX ortamında bile (bir uyum hatası) /bin/sh
bile yorumlanacaktır /usr/xpg4/bin/find
.
csh -c myscript
csh
ile başlarsa #
, sh
aksi takdirde yorumlayacaktır .
Sonuç olarak, nasıl ve ne tarafından çağrılacağını bilmiyorsanız, bu komut dosyasını yorumlamak için hangi kabuğun kullanılacağından emin olamazsınız.
Her durumda, read -p
bir bash
emin komut tarafından yorumlanır emin olmak isteyeceksiniz yüzden, -sadece sözdizimi bash
(ve bu yanıltıcı önlemek .sh
uzantısı). bash
Yürütülebilir dosyanın yolunu biliyor ve kullanıyorsunuz:
#! /path/to/bash -
read -p ...
Yoksa denemek ve bir güvenebilirsiniz $PATH
ait arama bash
çalıştırılabilir (varsayarak bash
kullanılarak yüklenir):
#! /usr/bin/env bash
read -p ...
( env
neredeyse her yerde bulunur /usr/bin
). Alternatif olarak, POSIX + Bourne uyumlu yapabilirsiniz, bu durumda kullanabilirsiniz /bin/sh
. Tüm sistemlerde bir /bin/sh
. Bunların çoğunda (çoğunlukla) POSIX uyumlu olacak, ancak şimdi ve sonra bir Bourne kabuğu bulabilirsiniz.
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"