Załóżmy, że domyślną powłoką dla mojego konta jest zsh, ale otworzyłem terminal i odpaliłem bash i wykonałem skrypt o nazwie prac002.sh
, który interpreter powłoki będzie użyty do wykonania skryptu, zsh czy bash? Rozważ następujący przykład:
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % sudo cat /etc/passwd | grep papagolf
[sudo] password for papagolf:
papagolf:x:1000:1001:Rex,,,:/home/papagolf:/usr/bin/zsh
# papagolf's default shell is zsh
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % bash
# I fired up bash. (See that '%' prompt in zsh changes to '$' prompt, indicating bash.)
papagolf@Sierra:~/My Files/My Programs/Learning/Shell$ ./prac002.sh
Enter username : Rex
Rex
# Which interpreter did it just use?
** EDYCJA: ** Oto treść skryptu
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % cat ./prac002.sh
read -p "Enter username : " uname
echo $uname
. prac002.sh
umieść ją w źródle, jak w , zakładając, że twój skrypt znajduje się w bieżącym katalogu.. ./prac002.sh
a uruchomi się z bieżącą powłoką, tj. Kropką (.
), spacją (), a następnie ścieżką skryptu. Nazywa się to zbieraniem kropek w skrypcie. ;-)Odpowiedzi:
Ponieważ skrypt nie zaczyna się od
#!
linii shebang wskazującej, którego interpretera należy użyć, POSIX mówi, że :Frazowanie jest trochę niejednoznaczne, a różne powłoki mają różne interpretacje.
W takim przypadku Bash uruchomi skrypt za pomocą samego siebie . Z drugiej strony, jeśli zamiast tego uruchomiłeś go z zsh, zsh użyłby
sh
(cokolwiek, co jest w twoim systemie).Możesz sprawdzić to zachowanie w tym przypadku, dodając następujące wiersze do skryptu:
Zauważysz, że w Bash pierwszy wiersz wypisuje twoją wersję, podczas gdy drugi nigdy nic nie mówi, bez względu na to, jakiej powłoki używasz.
/bin/sh
, powiedzmy,dash
żadna linia nie wyświetli niczego, gdy skrypt jest wykonywany z zsh lub dash./bin/sh
link do Bash, zobaczysz wyjście pierwszego wiersza we wszystkich przypadkach./bin/sh
jest to inna wersja Bash niż bezpośrednio, zobaczysz inne dane wyjściowe po uruchomieniu skryptu bezpośrednio z bash i zsh.ps -p $$
Polecenie od odpowiedzi rools koszulka pokaże także przydatnych informacji na temat polecenia powłoki używanej do wykonywania skryptu.źródło
execl()
wywołania występuje, gdy skrypt powłoki nie zawiera shebang i jest wykonywany jakoscriptname
? Czy to się nie zdarza, gdy skrypt powłoki jest wykonywany jakobash scriptname
? Czy to się nie zdarza, gdy skrypt powłoki zawiera shebang i jest wykonywany jakoscriptname
?Ponieważ plik nie należy do żadnego z typów plików wykonywalnych rozpoznawanych przez system i przy założeniu, że masz uprawnienia do wykonania tego pliku,
execve()
wywołanie systemowe zwykle kończy się niepowodzeniem z błędemENOEXEC
( nie wykonywalnym ).To, co się wtedy stanie, zależy od aplikacji i / lub funkcji bibliotecznej użytej do wykonania polecenia.
Może to być na przykład powłoka, funkcja
execlp()
/execvp()
libc.Większość innych aplikacji będzie używać jednej z tych aplikacji po uruchomieniu polecenia. Będą wywoływać powłokę na przykład za pomocą
system("command line")
funkcji libc, która zwykle wywołuje wsh
celu parsowania tej linii poleceń (której ścieżkę można określić w czasie kompilacji (jak/bin/sh
vs/usr/xpg4/bin/sh
w Solarisie)) lub wywołuje powłokę przechowywaną$SHELL
przez siebie jakvi
z jego!
poleceniem lubxterm -e 'command line'
wieloma innymi poleceniami (su user -c
zamiast tego wywoła powłokę logowania użytkownika$SHELL
).Zasadniczo plik tekstowy bez shebang, który się nie zaczyna,
#
jest uważany zash
skrypt. Któresh
to będzie się różnić.execlp()
/execvp()
, poexecve()
powrocieENOEXEC
zwykle wywołujesh
na nim. W przypadku systemów, które mają więcej niż jeden,sh
ponieważ mogą być zgodne z więcej niż jednym standardem, cosh
zwykle określa się w czasie kompilacji (aplikacji używającejexecvp()
/execlp()
przez połączenie innego obiektu blob kodu, który odnosi się do innej ścieżkish
). Na przykład w/usr/xpg4/bin/sh
systemie Solaris będzie to (standard, POSIXsh
) lub/bin/sh
(powłoka Bourne'a (przestarzała powłoka) w systemie Solaris 10 i starszych wersjach, ksh93 w systemie Solaris 11).Jeśli chodzi o muszle, istnieje wiele odmian.
bash
, AT&Tksh
, powłoka Bourne'a zazwyczaj interpretuje sam skrypt (w procesie potomnym, o ile nieexec
jest używany) po symulacji aexecve()
, czyli nieuzbrojonej wszystkich nieobsługiwanych zmiennych, zamykając wszystkie fds close-on-exec, usuwając wszystkie niestandardowe pułapki, aliasy, funkcje ... (bash
zinterpretuje skrypt wsh
trybie).yash
wykona się ( taksh
jakargv[0]
wsh
trybie), aby go zinterpretować.zsh
,pdksh
,ash
Opartych powłoki zazwyczaj wywołaniash
(ścieżka, która określona w czasie kompilacji).Dla
csh
itcsh
(ish
niektórych wczesnych BSD), jeśli pierwszym znakiem pliku jest#
, to wykonają się, aby go zinterpretować, i wsh
przeciwnym razie. To sięga czasów sprzed shebang, w którychcsh
rozpoznawano#
jako komentarze, ale nie powłokę Bourne'a, więc#
była to wskazówka, że był to skrypt csh.fish
(przynajmniej wersja 2.4.0), po prostu zwraca błąd, jeśli sięexecve()
nie powiedzie (nie próbuje traktować go jako skryptu).Niektóre powłoki (jak
bash
AT&Tksh
) najpierw spróbują heurystycznie ustalić, czy plik prawdopodobnie ma być skryptem, czy nie. Może się więc okazać, że niektóre powłoki odmówią wykonania skryptu, jeśli w pierwszych kilku bajtach ma znak NUL.Zauważ też, że jeśli
execve()
nie powiedzie się ENOEXEC, ale plik ma linię shebang, niektóre powłoki próbują sami interpretować tę linię shebang.Oto kilka przykładów:
$SHELL
jest/bin/bash
,xterm -e 'myscript with args'
będziemyscript
interpretowane przezbash
wsh
trybie. Podczas gdyxterm -e myscript with args
,xterm
użyje,execvp()
więc skrypt zostanie zinterpretowany przezsh
.su -c myscript
na Solarisie 10, gdzieroot
powłoka logowania jest/bin/sh
i/bin/sh
jest powłoką Bourne'a, zostaniemyscript
zinterpretowana przez powłokę Bourne'a./usr/xpg4/bin/awk 'BEGIN{system("myscript")'
na Solarisie 10 będzie interpretowany przez/usr/xpg4/bin/sh
(to samo dla/usr/xpg4/bin/env myscript
).find . -prune -exec myscript {} \;
na Solarisie 10 (używanieexecvp()
) będzie interpretowane/bin/sh
nawet przez/usr/xpg4/bin/find
, nawet w środowisku POSIX (błąd zgodności).csh -c myscript
będzie interpretowany przez,csh
jeśli zacznie od#
, wsh
przeciwnym razie.Podsumowując, nie możesz być pewien, która powłoka zostanie użyta do interpretacji tego skryptu, jeśli nie wiesz jak i przez co zostanie on wywołany.
W każdym razie
read -p
jest tobash
tylko składnia, więc upewnij się, że skrypt jest interpretowany przezbash
(i unikaj tego mylącego.sh
rozszerzenia). Albo znasz ścieżkębash
pliku wykonywalnego i użyj:Lub możesz polegać na
$PATH
wyszukiwaniubash
pliku wykonywalnego (zakładając, żebash
jest zainstalowany), używając:(
env
jest prawie wszechobecny w/usr/bin
). Alternatywnie możesz ustawić kompatybilność POSIX + Bourne. W takim przypadku możesz użyć/bin/sh
. Wszystkie systemy będą miały/bin/sh
. W większości z nich będzie (w przeważającej części) kompatybilny z POSIX, ale możesz od czasu do czasu znaleźć tam powłokę Bourne'a.źródło
Gdy nie masz żadnej linii
#!
(zwanej shebang ), używa się sh . Aby to sprawdzić, możesz uruchomić następujący skrypt.Na moim komputerze dostaję
nawet jeśli moją domyślną powłoką jest zsh . Używa bash, ponieważ na moim komputerze polecenie sh jest implementowane przez bash .
źródło