Powiedzmy, że mam nazwany skrypt powłoki / bash test.sh
z:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
Mój test2.sh
wygląda tak:
#!/bin/bash
echo ${TESTVARIABLE}
To nie działa. Nie chcę przekazywać wszystkich zmiennych jako parametrów, ponieważ imho to przesada.
Czy jest inny sposób?
Odpowiedzi:
Masz w zasadzie dwie opcje:
export TESTVARIABLE
) przed uruchomieniem drugiego skryptu.. test2.sh
. Będzie działał w tej samej powłoce. Umożliwiłoby to łatwe dzielenie się bardziej złożonymi zmiennymi, takimi jak tablice, ale oznacza również, że drugi skrypt może modyfikować zmienne w powłoce źródłowej.AKTUALIZACJA:
Aby użyć
export
do ustawienia zmiennej środowiskowej, możesz użyć istniejącej zmiennej:To powinno działać w obie
bash
ish
.bash
umożliwia także łączenie go w następujący sposób:Działa to również w moim
sh
(tak się składabash
, że możesz użyćecho $SHELL
do sprawdzenia). Ale nie wierzę, że to gwarantuje, że w ogóle zadziałash
, więc najlepiej grać bezpiecznie i rozdzielić je.Każda zmienna eksportowana w ten sposób będzie widoczna w wykonywanych skryptach, na przykład:
popiół:
b.sh:
Następnie:
Fakt, że są to oba skrypty powłoki, jest również przypadkowy. Zmienne środowiskowe można przekazać do dowolnego wykonywanego procesu, na przykład jeśli zamiast tego użyjemy Pythona, może to wyglądać:
popiół:
b.py:
Pozyskiwanie:
Zamiast tego moglibyśmy uzyskać takie źródło:
popiół:
b.sh:
Następnie:
To mniej więcej „importuje” zawartość
b.sh
bezpośrednio i wykonuje ją w tej samej powłoce . Zauważ, że nie musieliśmy eksportować zmiennej, aby uzyskać do niej dostęp. To domyślnie udostępnia wszystkie zmienne, które masz, a także pozwala drugiemu skryptowi dodawać / usuwać / modyfikować zmienne w powłoce. Oczywiście w tym modelu oba skrypty powinny być w tym samym języku (sh
lubbash
). Aby podać przykład, w jaki sposób możemy przekazywać wiadomości w tę iz powrotem:popiół:
b.sh:
Następnie:
Działa to równie dobrze w
bash
. Ułatwia także udostępnianie bardziej złożonych danych, których nie można wyrazić jako zmienną środowiskową (przynajmniej bez dużego obciążenia z twojej strony), takich jak tablice lub tablice asocjacyjne.źródło
Błąd krytyczny dał bezpośrednią możliwość: zdobądź swój drugi skrypt! jeśli obawiasz się, że ten drugi skrypt może zmienić niektóre z twoich cennych zmiennych, zawsze możesz go zdobyć w podpowłoce:
Nawiasy sprawią, że źródło stanie się w podpowłoce, dzięki czemu powłoka nadrzędna nie zobaczy modyfikacji, które
test2.sh
mogłyby zostać wykonane.Jest jeszcze jedna możliwość, z którą należy zdecydowanie się tutaj odwołać: use
set -a
.Z odniesienia do POSIX
set
:Z podręcznika Bash :
Więc w twoim przypadku:
Zauważ, że specyfikacje określają tylko, że
set -a
zmienna jest oznaczona do eksportu. To jest:odbije się echem,
c
a nie pustą linią anib
(czyliset +a
nie odznacza dla eksportu, ani nie „zapisuje” wartości przypisania tylko dla eksportowanego środowiska). Jest to oczywiście najbardziej naturalne zachowanie.Wniosek: użycie
set -a
/set +a
może być mniej uciążliwe niż ręczne eksportowanie wszystkich zmiennych. Jest lepszy niż pozyskiwanie drugiego skryptu, ponieważ będzie działał dla każdego polecenia, nie tylko dla tego napisanego w tym samym języku powłoki.źródło
Jest tak naprawdę łatwiejszy sposób niż ponowne eksportowanie, rozbrajanie lub pozyskiwanie zasobów (przynajmniej w bash, o ile jesteś w stanie ręcznie przekazać zmienne środowiskowe):
niech a.sh będzie
i b.sh be
Zaobserwowana moc wyjściowa to
Magia leży w ostatnim wierszu
a.sh
, gdzieMessage
tylko na czas trwania wywołania./b.sh
jest ustawiona na wartośćsecret
za.sh
. Zasadniczo przypomina trochę nazwane parametry / argumenty. Co więcej, działa nawet w przypadku zmiennych takich jak$DISPLAY
, które kontrolują, w którym X serwerze uruchamia się aplikacja.Pamiętaj, że długość listy zmiennych środowiskowych nie jest nieskończona. W moim systemie ze względnie waniliowym jądrem
xargs --show-limits
mówi mi, że maksymalny rozmiar bufora argumentów to 2094486 bajtów. Teoretycznie źle używasz skryptów powłoki, jeśli Twoje dane są większe (rury, ktoś?)źródło
Dodając do odpowiedzi Fatal Error, istnieje jeszcze jeden sposób na przekazanie zmiennych do innego skryptu powłoki.
Powyższe sugerowane rozwiązanie ma pewne wady:
using Export
: Spowoduje to, że zmienna będzie poza zakresem, co nie jest dobrą praktyką projektową.using Source
: Może to powodować kolizje nazw lub przypadkowe zastąpienie predefiniowanej zmiennej w innym pliku skryptu powłoki, który pozyskał inny plik.Jest jeszcze jedno proste rozwiązanie, którego możemy użyć. Biorąc pod uwagę opublikowany przez Ciebie przykład,
test.sh
test2.sh
wynik
Ważne jest również, aby pamiętać, że
""
są one konieczne, jeśli przekazujemy ciągi wielosłówowe. Biorąc jeszcze jeden przykładmaster.sh
slave1.sh
slave2.sh
wynik
Dzieje się tak z powodów dokładnie opisanych w tym linku
źródło
source
jest w rzeczywistości dobrą rzeczą. Jeśli chodzi o twoje zmartwienie: przypadkowe zastąpienie predefiniowanej zmiennej zawsze możesz uzyskać źródło w podpowłoce. To całkowicie rozwiązuje problem.( . ./test2.sh )
. Nawiasy powodują, że Bash uruchamia swoją zawartość w podpowłoce.W Bash, jeśli eksportujesz zmienną w podpowłoce, używając nawiasów, jak pokazano, unikniesz wycieku eksportowanych zmiennych:
Zaletą jest to, że po uruchomieniu skryptu z wiersza poleceń nie zobaczysz wycieku $ TESTVARIABLE do twojego środowiska:
źródło
$
polecenia) nigdy nie zobaczy wyeksportowanego$TESTVARIABLE
. Export tylko przekazuje kopię zmiennej do kolejnych procesów potomnych . Nie jest możliwe przekazywanie zmiennych z powrotem do łańcucha do procesów nadrzędnych, chyba że zapisuje się wartość w pamięci i odczytuje tę pamięć później w skrypcie procesu nadrzędnego. Przesyłanie potokowe do drugiej kopii skryptu nadrzędnego jest możliwe, ale nie byłby to ten sam proces . Doskonałe wyjaśnienie można znaleźć tutaj .Inną opcją jest użycie
eval
. Jest to odpowiednie tylko wtedy, gdy ciągi są zaufane. Pierwszy skrypt może powtórzyć przypisania zmiennych:echo "VAR=myvalue"
Następnie:
eval $(./first.sh) ./second.sh
To podejście jest szczególnie interesujące, gdy drugi skrypt, dla którego chcesz ustawić zmienne środowiskowe, nie znajduje się w bashu, a ty też nie chcesz
export
zmiennych, być może dlatego, że są wrażliwe i nie chcesz, aby trwały.źródło
Innym sposobem, który jest dla mnie trochę łatwiejszy, jest stosowanie nazwanych potoków. Nazwane potoki umożliwiły synchronizację i wysyłanie wiadomości między różnymi procesami.
Wstydzić:
B.bash:
Stosowanie:
B.bash będzie czekał na wiadomość i gdy tylko A.bash wyśle wiadomość, B.bash będzie kontynuował pracę.
źródło