W tym pytaniu przeczytałem :
bash obsługuje przełącznik --posix, co czyni go bardziej zgodnym z POSIX. Próbuje również naśladować POSIX, jeśli zostanie wywołany jako sh .
Powyższy cytat zakłada, że /bin/sh
jest to link, który wskazuje /bin/bash
.
Ale nie do końca rozumiem, co oznacza „wywoływany jako sh” .
Powiedz, że mam następujący skrypt o nazwie „script.sh”:
#!/bin/bash
echo "Hello World"
Proszę powiedzieć mi w każdym z poniższych przypadków, czy skrypt będzie uruchamiany w bash
trybie normalnym , czy w trybie POSIX (załóżmy, że wykonałem następujące polecenia w uruchomionym terminalu bash
):
sh script.sh
bash script.sh
./script.sh
Teraz powiedz, że mam następujący skrypt, który nazywa się „script.sh” (który jest podobny do powyższego skryptu, ale bez shebang):
echo "Hello World"
Proszę powiedzieć mi w każdym z poniższych przypadków, czy skrypt będzie uruchamiany w bash
trybie normalnym , czy w trybie POSIX (załóżmy, że wykonałem następujące polecenia w uruchomionym terminalu bash
):
sh script2.sh
bash script2.sh
./script2.sh
Odpowiedzi:
Tylko przypadki 1 i 4 będą działać w trybie POSIX (zakładając, że
sh
jest to bash, a nie jakaś inna implementacja sh). Każdy przypadek, który jawnie wywołujebash
bez--posix
, nie będzie, czy to z shebang, czy nie. Każdy przypadek, który wyraźniesh
wywoła, będzie. Shebang jest używany tylko wtedy, gdy żadna powłoka nie została już wyraźnie uruchomiona dla skryptu.Przypadek 6, jeśli twój terminal jest uruchomiony
bash
, nie będzie działał w trybie POSIX, a Bash wywoła go przy użyciu samego siebie. Gdyby twój terminal zamiast tego działał zsh, przypadek 6 również działałby w trybie POSIX. POSIX jest niejednoznaczny co do tego, co powinno się zdarzyć w takim przypadku , a Bash i zsh dokonali tam różnych wyborów. Bash wywołuje skrypt za pomocą samego siebie, podczas gdy zsh używash
(cokolwiek by się nie stało). Inne pociski również różnią się w tym punkcie.Jednym prostym sposobem na określenie, w jakim trybie się znajdujesz, jest utworzenie skryptu:
co zakończy się niepowodzeniem z błędem w trybie POSIX , ale poda instrukcje użytkowania
kill
poza nim. Jest to łatwe rozróżnienie i działa w szerokim zakresie wersji Bash, sięgając wstecz, na ile możesz się natknąć.źródło
bash
do uruchomienia w trybie POSIX, takie jakPOSIXLY_CORRECT
zmienna środowiskowa lubSHELLOPTS=posix
.[ -o posix ]
jest bardziej oczywistym sposobem sprawdzenia, czy działasz w trybie posix w bash (nie w innych powłokach (z wyjątkiem yash), więc nie chciałbyś tego robić wsh
skrypcie).POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'
wyjściayes
`„Wywołany jako” odnosi się do wszystkiego, co proces uruchamiający Bash umieszcza w argumencie wiersza poleceń „zero”
argv[0]
.Kiedy program jest uruchamiany z
exec*()
syscallami , tak naprawdę nie znają nazwy pliku binarnego zawierającego program, ale zamiast tego proces wywoływania może umieścić tam, co chce. Zwykle oczywiście nazwa jest pobierana z systemu plików, więc jeśli uruchomisz/bin/sh
, to właśnie tam zostanie umieszczona. A jeśli/bin/sh
jest to Bash, nie musi to być dowiązanie symboliczne, może to być dowiązanie twarde lub po prostu kolejna kopia programu powłoki.Jako przykład ustawienia „nazwy programu”,
exec
polecenie Bash może ustawić argument zerowy z-a
opcją. (Możemy zrobić to samo z Perlem lub bezpośrednio z C itp.)Oto
myname
prosty program C, który po prostu wypisuje swój zerowy argument, nazwę, którą widzi:Źródło:
Ale, aby odpowiedzieć na ponumerowane pytania ...
(1 i 4) bieganie
sh somescript
uruchomi wszystko, cosh
jest na twoimPATH
, prawdopodobnie,/bin/sh
ale prawdopodobnie coś takiego/usr/xpg4/bin/sh
.sh
.sh
, ale działa w trybie „kompatybilnym z SH”, który ma na celu być kompatybilnym z powłoką Bourne'a i jest nieco inny niż tryb zgodny z POSIX w obu tych powłokach .(2 i 5) Bieganie
bash somescript
będzie działało w zwykłym trybie Bash (znowu, oczywiście zależy to od tego, cobash
maszPATH
).(3) Tutaj nazwa skryptu jest podawana bezpośrednio do wywołania systemowego zamiast pliku programu. Jądro czyta wiersz hashbanga i używa go do uruchomienia skryptu.
(6) To jest złożony. Jest podobny do (3), ale wywołanie systemowe do uruchomienia programu kończy się niepowodzeniem (
ENOEXEC (Exec format error)
), ponieważ nie ma linii mieszania. Co dzieje się dalej, zależy od tego, czy powłoka że używasz jest się w trybie POSIX. POSIX wymaga, aby powłoka zgodna z POSIX zachowywała się w określony sposób w odpowiedzi naENOEXEC
. Istnieje jednak pewien margines swobody w „poleceniu równoważnym wywołaniu powłoki”, co oznacza, że różne powłoki wykonują różne czynności./bin/sh
z nazwą skryptu wstawioną przed innymi argumentami jako pierwszym argumentem wiersza poleceń. Powłoka Z, powłoka Almquista i powłoka Korna (próbują) wywołać powłokę zgodną z POSIX, zakładając, że/bin/sh
program jest jednym.źródło
int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
Wykonywana powłoka jest albo wywoływana w wierszu poleceń, albo w shebang (jeśli wiersz poleceń tego nie określa).
Tak więc wersje 1 i 4 będą działać z
sh
, 2 i 5 z bash, a 6 może nie działać, jeśli używasz sh (i niektórych innych) interaktywnie. Bash zaczyna skrypt. Ksh też. Zsh zaczyna to jako sh.Tylko te, które zostały uruchomione,
sh
będą korzystać z opcji posix, jeśli bash jest połączony z/bin/sh
.Dodaj ten wiersz do skryptu, aby wykryć, czy jest uruchomiona jakaś wersja bash ksh lub zsh:
źródło