Krótka odpowiedź
W twoim pytaniu drugie polecenie nie używa ani .
wbudowanej powłoki, ani source
wbudowanej. Zamiast tego faktycznie uruchamiasz skrypt w osobnej powłoce, wywołując go po imieniu, tak jak w przypadku każdego innego pliku wykonywalnego. Daje to oddzielny zestaw zmiennych (chociaż jeśli eksportujesz zmienną w jej powłoce nadrzędnej, będzie to zmienna środowiskowa dla dowolnego procesu potomnego , a zatem zostanie uwzględniona w zmiennych podrzędnej powłoki ). Jeśli zmienisz na /
spację, uruchomiłbyś go z .
wbudowanym odpowiednikiem source
.
Rozszerzone objaśnienie
Oto składnia source
wbudowanej powłoki, która wykonuje zawartość skryptu w bieżącej powłoce (a tym samym ze zmiennymi bieżącej powłoki):
source testenv.sh
To jest składnia .
wbudowanego, który robi to samo, co source
:
. testenv.sh
Jednak ta składnia uruchamia skrypt jako plik wykonywalny, uruchamiając nową powłokę, aby go uruchomić:
./testenv.sh
To nie używa .
wbudowanego. Jest raczej .
częścią ścieżki do wykonywanego pliku. Ogólnie mówiąc, możesz uruchomić dowolny plik wykonywalny w powłoce, wywołując go z nazwą zawierającą co najmniej jeden /
znak. ./
Najłatwiejszym sposobem jest uruchomienie pliku w bieżącym katalogu . Jeśli bieżący katalog nie znajduje się w twoim PATH
, nie możesz uruchomić skryptu za pomocą polecenia testenv.sh
. Zapobiega to przypadkowemu uruchomieniu plików w bieżącym katalogu, gdy zamierzają wykonać polecenie systemowe lub inny plik, który istnieje w katalogu wymienionym w PATH
zmiennej środowiskowej.
Ponieważ uruchomienie pliku według nazwy (zamiast z source
lub .
) uruchamia go w nowej powłoce, będzie on miał swój własny zestaw zmiennych powłoki. Nowa powłoka dziedziczy zmienne środowiskowe z procesu wywołującego (którym w tym przypadku jest powłoka interaktywna), a te zmienne środowiskowe stają się zmiennymi powłoki w nowej powłoce. Jednak, aby zmienna powłoki została przekazana do nowej powłoki, musi mieć miejsce jedna z następujących sytuacji:
Zmienna powłoki została wyeksportowana, przez co jest zmienną środowiskową. Użyj do tego export
wbudowanej powłoki. W twoim przykładzie możesz użyć, export MY_VAR=12345
aby ustawić i wyeksportować zmienną w jednym kroku, lub jeśli jest już ustawiona, możesz po prostu użyć export MY_VAR
.
Zmienna powłoki jest jawnie ustawiona i przekazywana dla uruchomionego polecenia, co powoduje, że jest zmienną środowiskową na czas wykonywania polecenia. To zwykle realizuje że:
MY_VAR=12345 ./testenv.sh
Jeśli MY_VAR
jest to zmienna powłoki, która nie została wyeksportowana, możesz nawet uruchomić testenv.sh
ją MY_VAR
jako zmienną środowiskową, ustawiając ją na sobie :
MY_VAR="$MY_VAR" ./testenv.sh
./
Składnia skryptów wymaga do działania wiersza skrótu (poprawnie)
Nawiasem mówiąc, należy pamiętać, że przy wywołaniu pliku wykonywalnego według nazwy jak wyżej (a nie z .
lub source
Shell Zabudowy), co Shell program jest używany do uruchamiania jest nie zwykle określana przez co powłoka używasz go od . Zamiast:
W przypadku plików binarnych jądro może być skonfigurowane do uruchamiania plików określonego typu. Sprawdza dwa pierwsze bajty pliku pod kątem „magicznej liczby”, która wskazuje, jaki to binarny plik wykonywalny. W ten sposób można uruchamiać binarne pliki wykonywalne.
Jest to oczywiście niezwykle ważne, ponieważ skrypt nie może działać bez powłoki lub innego interpretera, który jest wykonywalnym plikiem binarnym! Ponadto wiele poleceń i aplikacji to skompilowane pliki binarne, a nie skrypty.
( #!
to tekstowa reprezentacja „magicznej liczby” wskazującej tekst wykonywalny).
W przypadku plików, które powinny działać w powłoce lub innym interpretowanym języku, pierwszy wiersz wygląda następująco:
#!/bin/sh
/bin/sh
może być zastąpiony przez dowolną inną powłokę lub interpreter przeznaczony do uruchomienia programu. Na przykład program w języku Python może zaczynać się od wiersza:
#!/usr/bin/python
Linie te nazywane są hashbang, shebang i wieloma innymi podobnymi nazwami. Zobacz ten wpis FOLDOC , ten artykuł w Wikipedii i Czy tłumacz! # / Bin / sh jest odczytywany? po więcej informacji.
Jeśli plik tekstowy jest oznaczony jako wykonywalny i uruchamiasz go ze swojej powłoki (jak ./filename
), ale nie zaczyna się od #!
, jądro nie wykonuje go. Jednak widząc, że tak się stało, twoja powłoka spróbuje ją uruchomić, przekazując swoją nazwę do jakiejś powłoki. Istnieje niewiele wymagań dotyczących tego, co to jest powłoka ( „powłoka wykona polecenie równoważne z wywołaniem powłoki ...” ). W praktyce niektóre powłoki - w tym bash
* - uruchamiają inne wystąpienia, podczas gdy inne używają/bin/sh
. Gorąco polecam, aby tego uniknąć i zamiast tego użyć linii hashbang (lub uruchomić skrypt, przekazując go do pożądanego interpretera, np bash filename
.).
* Podręcznik GNU Bash , 3.7.2 Wyszukiwanie i wykonywanie poleceń : „Jeśli wykonanie się nie powiedzie, ponieważ plik nie jest w formacie wykonywalnym, a plik nie jest katalogiem, zakłada się, że jest to skrypt powłoki i powłoka wykonuje go zgodnie z opisem w skryptach powłoki ”.
source
to, że funkcje stały się dostępne z bash bez potrzeby ładowania lub ponownego uruchamiania. Przykład#!/bin/bash function olakease {echo olakease;}
. Po załadowaniusource file.sh
możesz bezpośrednio zadzwonićolakease
z bash. Naprawdę to lubię. Źródło wykonuje następnie ładuje wiele rzeczy, kropka.
służy tylko do wykonania i jest jak użyciebash file.sh
.
ma również takie zachowanie:. file.sh
isource file.sh
rób dokładnie to samo, włączając w to zachowanie funkcji zdefiniowanych wfile.sh
. (Być może myślisz o tym./file.sh
, co jest inne. Ale to nie korzysta z.
wbudowanego; zamiast tego.
jest częścią ścieżki.)Tak, czegoś brakuje.
Myślę, że mylisz „.” oznacza to bieżący katalog, jak w „
./testenv.sh
i”. to znaczysource
(które jest wbudowanym poleceniem). Tak więc w przypadku, gdy „.” oznacza,source
że byłoby. ./testenv.sh
. Ma sens?Spróbuj tego:
źródło
./
Informuje go dokładnie tam, gdzie plik to bez niego, bash będzie wyglądać ścieżka pierwsza, a następnie spróbuj bieżący dir jeśli go nie znajdzie. Jeśli bash działa w trybie POSIX i nie podasz ścieżki do pliku (np../
), Przeszuka on tylko PATH i nie znajdzie pliku, jeśli bieżący katalog nie znajduje się w PATH.source
(i.
) faktycznie najpierw sprawdzi $ PATH, nawet jeśli tak naprawdę nie uruchamiają skryptu w zwykłym sensie. Mój (poprzedni) komentarz był niepoprawny.