2009-12-11 15:24:17 +0000 2009-12-11 15:24:17 +0000
302
302

Jaka jest różnica między wykonywaniem skryptu Bash a jego pozyskiwaniem?

Jaka jest różnica między wykonaniem skryptu Bash takiego jak A a pozyskiwaniem skryptu Bash takiego jak B?

A
> ./myscript

B
> source myscript

Odpowiedzi (6)

369
369
369
2010-08-16 21:58:48 +0000

Odbiorca skryptu uruchomi polecenia 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 wykonaj w przeciwnym wypadku.

Jeśli nadal jesteś zdezorientowany, czytaj dalej.

Terminologia

Aby wyjaśnić pewne powszechne nieporozumienia dotyczące składni execute i składni source:

./myscript

To wykona 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żący katalog zwykle nie jest (i zwykle nie powinien być) w $PATH.

myscript

To spowoduje wykonanie myscript, jeśli plik jest wykonywalny i znajduje się w jakimś katalogu w $PATH.

source myscript

Spowoduje to zasilenie myscript. Plik nie musi być wykonywalny, ale musi być poprawnym skryptem powłoki. Plik może znajdować się w bieżącym katalogu lub w katalogu w $PATH.

. myscript

To również będzie źródło myscript. Ta “pisownia” jest oficjalną pisownią zdefiniowaną przez POSIX . Bash zdefiniował source jako alias do kropki.

Demonstracja

Rozważmy myscript.sh z następującą zawartoś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

Zanim wykonamy skrypt, najpierw sprawdzamy aktualne środowisko:

$ env | grep FOO
$ echo $PWD
/home/lesmana

Zmienna FOO nie jest zdefiniowana i znajdujemy się w katalogu domowym.

Teraz wykonujemy wykonanie pliku:

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Sprawdzamy ponownie środowisko:

$ env | grep FOO
$ echo $PWD
/home/lesmana

Zmienna FOO nie jest ustawiona, a katalog roboczy nie uległ zmianie.

Wyjście skryptu wyraźnie pokazuje, że zmienna została ustawiona i katalog został zmieniony. Późniejsze sprawdzenie pokazuje, że zmienna nie jest ustawiona, a katalog nie został zmieniony. Co się stało? Zmiany zostały dokonane w nowej powłoce. Powłoka current wywołała nową powłokę, aby uruchomić skrypt. Skrypt jest uruchamiany w nowej powłoce i wszystkie zmiany w środowisku zaczynają obowiązywać w nowej powłoce. Po wykonaniu skryptu nowa powłoka jest niszczona. Wszystkie zmiany w środowisku w nowej powłoce są niszczone wraz z nową powłoką. Jedynie tekst wyjściowy jest wypisywany w bieżącej powłoce.

Teraz pochodzimy z pliku:

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Sprawdzamy ponownie środowisko:

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

Zmienna FOO jest ustawiona, a katalog roboczy uległ zmianie.

Wykonanie skryptu nie powoduje utworzenia nowej powłoki. Wszystkie polecenia są wykonywane w bieżącej powłoce, a zmiany w środowisku zaczynają obowiązywać w bieżącej powłoce.

Zauważ, że w tym prostym przykładzie wynik wykonania jest taki sam, jak źródło skryptu. Niekoniecznie zawsze tak jest.

Inna demonstracja

Rozważmy następujący skrypt pid.sh:

#!/bin/sh
echo $$

(zmienna specjalna $$ interpretowana jest jako PID aktualnie uruchomionego procesu powłoki)

Najpierw wypisz PID bieżącej powłoki:

$ echo $$
25009

Źródło skryptu:

$ source pid.sh
25009

Wykonaj skrypt, zwróć uwagę na PID:

$ ./pid.sh
25011

Źródło ponownie:

$ source pid.sh
25009

Wykonaj ponownie:

$ ./pid.sh
25013

Możesz zobaczyć, że źródło skryptu działa w tym samym procesie, podczas gdy wykonywanie skryptu tworzy nowy proces za każdym razem. Tym nowym procesem jest nowa powłoka, która została utworzona do wykonania skryptu. Sourcing skryptu nie tworzy nowej powłoki i dlatego PID pozostaje taki sam.

Podsumowanie

Zarówno pozyskiwanie jak i wykonywanie skryptu uruchomi polecenia w skrypcie linia po linii, tak jakbyś wpisał te polecenia ręcznie linia po linii.

Różnice są następujące:

  • Kiedy wykonujesz skrypt, otwierasz nową powłokę, wpisujesz polecenia w nowej powłoce, kopiujesz dane wyjściowe z powrotem do bieżącej powłoki, a następnie zamykasz nową powłokę. Wszelkie zmiany w środowisku będą obowiązywać tylko w nowej powłoce i zostaną utracone po zamknięciu nowej powłoki.
  • Kiedy zasilasz skrypt, wpisujesz polecenia w swojej bieżącej powłoce. Wszelkie zmiany w środowisku będą obowiązywać i pozostaną w twojej bieżącej powłoce.

Użyj source jeśli chcesz by skrypt zmienił środowisko w twojej aktualnie uruchomionej powłoce. użyj execute w przeciwnym wypadku.


Zobacz także:

23
23
23
2009-12-11 15:35:56 +0000

Wykonywanie skryptu uruchamia go w oddzielnym procesie potomnym, tj. do przetwarzania skryptu wywoływana jest oddzielna instancja powłoki. Oznacza to, że wszelkie zmienne środowiskowe itp. zdefiniowane w skrypcie nie mogą być aktualizowane w powłoce rodzica (bieżącej).

Sourcing skryptu oznacza, że jest on parsowany i wykonywany przez samą bieżącą powłokę. To tak, jakbyś wpisał zawartość skryptu. Z tego powodu, pozyskiwany skrypt nie musi być wykonywalny. Ale musi być wykonywalny, jeśli go wykonujesz, oczywiście.

Jeśli masz argumenty pozycyjne w bieżącej powłoce, to są one niezmienione.

Więc jeśli mam plik a.sh zawierający:

echo a $*

i robię:

$ set `date`
$ source ./a.sh

otrzymam coś takiego jak:

a Fri Dec 11 07:34:17 PST 2009

Natomiast:

$ set `date`
$ ./a.sh

daje mi:

a

Mam nadzieję, że to pomoże.

9
9
9
2009-12-11 15:27:08 +0000

Sourcing jest zasadniczo tym samym, co wpisywanie każdej linii skryptu w wierszu poleceń po kolei…

Wykonanie uruchamia nowy proces, a następnie uruchamia każdą linię skryptu, modyfikując tylko bieżące środowisko tym, co zwraca.

6
6
6
2012-02-23 07:27:43 +0000

Dodatkowo, wykonanie skryptu jako ./myscript wymaga uprawnienia execute dla pliku myscript, podczas gdy sourcing nie wymaga żadnego uprawnienia execute. Dlatego chmod +x myscript nie jest wymagane przed source myscript.

5
5
5
2009-12-11 15:25:38 +0000

Sourcing dostaniesz wszystkie dodatkowe zmienne zdefiniowane w skrypcie.
Więc jeśli masz configi lub definicje funkcji, powinieneś je pozyskać, a nie wykonywać. Wykonania są niezależne od środowiska rodzica.

2
2
2
2015-03-27 14:04:20 +0000

Polecenie source wykonuje podany skrypt (zezwolenie na wykonanie jest nieobowiązkowe )w bieżącym środowisku powłoki, natomiast ./ wykonuje podany wykonalny skrypt w nowej powłoce.

Sprawdź również tę odpowiedź dla przykładu: https://superuser.com/a/894748/432100