Jaka jest różnica między wykonywaniem skryptu Bash, takiego jak A, a pozyskiwaniem skryptu Bash, takiego jak B?
A
> ./myscript
B
> source myscript
Jaka jest różnica między wykonywaniem skryptu Bash, takiego jak A, a pozyskiwaniem skryptu Bash, takiego jak B?
A
> ./myscript
B
> source myscript
Odpowiedzi:
Pozyskanie skryptu spowoduje uruchomienie poleceń w bieżącym procesie powłoki.
Wykonanie skryptu spowoduje uruchomienie poleceń w nowym procesie powłoki.
Użyj źródła, jeśli chcesz, aby skrypt zmienił środowisko w aktualnie uruchomionej powłoce. użyj wykonać inaczej.
Jeśli nadal jesteś zdezorientowany, czytaj dalej.
Aby wyjaśnić niektóre typowe nieporozumienia dotyczące składni do wykonania i składni do źródła:
./myscript
Będzie to execute myscript
pod warunkiem, że plik jest wykonywalny i znajduje się w bieżącym katalogu. Wiodąca kropka i ukośnik ( ./
) oznaczają bieżący katalog. Jest to konieczne, ponieważ bieżącego katalogu zwykle nie ma (i zwykle nie powinno być) $PATH
.
myscript
Będzie to wykonać myscript
, jeśli plik jest wykonywalny i znajduje się w jakimś katalogu w $PATH
.
source myscript
To będzie źródło myscript
. Plik nie musi być wykonywalny, ale musi być prawidłowym skryptem powłoki. Plik może znajdować się w bieżącym katalogu lub w katalogu w $PATH
.
. myscript
To również źródło myscript
. Ta „pisownia” jest oficjalna zgodnie z definicją POSIX . Bash zdefiniowany source
jako alias do kropki.
Rozważ myscript.sh
następujące treści:
#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD
Przed wykonaniem skryptu najpierw sprawdzamy bieżące środowisko:
$ env | grep FOO
$ echo $PWD
/home/lesmana
Zmienna FOO
nie jest zdefiniowana i jesteśmy w katalogu domowym.
Teraz wykonujemy plik:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Sprawdź ponownie środowisko:
$ env | grep FOO
$ echo $PWD
/home/lesmana
Zmienna FOO
nie jest ustawiona, a katalog roboczy nie zmienił się.
Dane wyjściowe skryptu wyraźnie pokazują, że zmienna została ustawiona, a katalog został zmieniony. Następnie kontrola pokazuje, że zmienna nie jest ustawiona, a katalog się nie zmienia. Co się stało? Zmiany zostały wprowadzone w nowej powłoce. Prąd powłoki zrodził nową powłokę, aby uruchomić skrypt. Skrypt działa w nowej powłoce, a wszystkie zmiany w środowisku obowiązują w nowej powłoce. Po zakończeniu skryptu nowa powłoka jest niszczona. Wszystkie zmiany środowiska w nowej powłoce są niszczone przez nową powłokę. Tylko tekst wyjściowy jest drukowany w bieżącej powłoce.
Teraz źródło pliku:
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Sprawdź ponownie środowisko:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
Zmienna FOO została ustawiona, a katalog roboczy zmienił się.
Pozyskanie skryptu nie tworzy nowej powłoki. Wszystkie polecenia są uruchamiane w bieżącej powłoce, a zmiany w środowisku obowiązują w bieżącej powłoce.
Zauważ, że w tym prostym przykładzie wynik wykonania jest taki sam, jak pozyskiwanie skryptu. Nie zawsze tak jest.
Rozważ następujący skrypt pid.sh
:
#!/bin/sh
echo $$
(specjalna zmienna $$
rozwija się do PID aktualnie działającego procesu powłoki)
Najpierw wydrukuj PID bieżącej powłoki:
$ echo $$
25009
Źródło skryptu:
$ source pid.sh
25009
Uruchom skrypt, zwróć uwagę na PID:
$ ./pid.sh
25011
Źródło ponownie:
$ source pid.sh
25009
Wykonaj ponownie:
$ ./pid.sh
25013
Widać, że pozyskiwanie skryptu odbywa się w tym samym procesie, a wykonanie skryptu powoduje utworzenie nowego procesu za każdym razem. Ten nowy proces to nowa powłoka, która została stworzona do wykonania skryptu. Pozyskanie skryptu nie tworzy nowej powłoki, a zatem PID pozostaje taki sam.
Zarówno wyszukiwanie, jak i wykonywanie skryptu spowoduje uruchamianie poleceń w skrypcie wiersz po wierszu, tak jakbyś wpisywał te polecenia ręcznie wiersz po wierszu.
Różnice są następujące:
Użyj źródła, jeśli chcesz, aby skrypt zmienił środowisko w aktualnie uruchomionej powłoce. użyj wykonać inaczej.
Zobacz też:
source myscript.sh
a . myscript.sh
?
Wykonanie skryptu powoduje uruchomienie go w osobnym procesie potomnym, tzn. W celu przetworzenia skryptu wywoływana jest osobna instancja powłoki. Oznacza to, że żadnych zmiennych środowiskowych itp. Zdefiniowanych w skrypcie nie można aktualizować w powłoce nadrzędnej (bieżącej).
Pozyskanie skryptu oznacza, że jest on analizowany i wykonywany przez samą bieżącą powłokę. To tak, jakbyś wpisał treść skryptu. Z tego powodu skrypt nie musi być wykonywalny. Ale oczywiście musi być wykonywalny.
Jeśli masz argumenty pozycyjne w bieżącej powłoce, są one niezmienione.
Więc jeśli mam plik a.sh
zawierający:
echo a $*
i robię:
$ set `date`
$ source ./a.sh
Dostaję coś takiego:
a Fri Dec 11 07:34:17 PST 2009
Natomiast:
$ set `date`
$ ./a.sh
daje mi:
a
Mam nadzieję, że to pomaga.
pozyskiwanie jest zasadniczo takie samo, jak wpisywanie każdej linii skryptu w wierszu polecenia pojedynczo ...
Wykonanie rozpoczyna nowy proces, a następnie uruchamia każdą linię skryptu, modyfikując tylko bieżące środowisko o to, co zwraca.
Oprócz powyższego wykonanie skryptu ./myscript
wymaga uprawnień do wykonywania skryptu myscript, podczas gdy pozyskiwanie nie wymaga uprawnień do wykonywania. Dlatego wcześniej chmod +x myscript
nie jest to wymaganesource myscript
bash myscript
.
Pozyskiwanie zawiera wszystkie dodatkowe zmienne zdefiniowane w skrypcie.
Więc jeśli masz konfiguracje lub definicje funkcji, powinieneś je pobrać, a nie wykonać. Wykonania są niezależne od środowiska rodziców.
Jeśli dobrze pamiętam, wykonanie skryptu uruchamia plik wykonywalny w #!
wierszu z plikiem skryptu jako argumentem (zazwyczaj uruchamianie nowej powłoki i efektywne pozyskiwanie skryptu do nowej powłoki, jak w przypadku #!/bin/sh
);
podczas gdy pozyskiwanie skryptu powoduje wykonanie każdego wiersza w bieżącym środowisku powłoki, co jest przydatne do mutowania bieżącej powłoki (na przykład umożliwiając zdefiniowanie funkcji powłoki i eksport zmiennych środowiskowych).
source
polecenie wykonuje podany skrypt (uprawnienie do wykonywania nie jest obowiązkowe ) w bieżącym środowisku powłoki, natomiast ./
wykonuje podany skrypt wykonywalny w nowej powłoce.
Sprawdź również tę odpowiedź, na przykład: https://superuser.com/a/894748/432100