Mam następującą funkcję rekurencyjną do ustawiania zmiennych środowiskowych:
function par_set {
PAR=$1
VAL=$2
if [ "" != "$1" ]
then
export ${PAR}=${VAL}
echo ${PAR}=${VAL}
shift
shift
par_set $*
fi
}
Jeśli wywołam to samo, zarówno ustawia zmienną, jak i echo na standardowe wyjście:
$ par_set FN WORKS
FN=WORKS
$ echo "FN = "$FN
FN = WORKS
Działa także przekierowanie standardowego pliku do pliku:
$ par_set REDIR WORKS > out
cat out
REDIR=WORKS
$ echo "REDIR = "$REDIR
REDIR = WORKS
Ale jeśli podłączę standardowe wyjście do innego polecenia, zmienna nie zostanie ustawiona:
$ par_set PIPE FAILS |sed -e's/FAILS/BARFS/'
PIPE=BARFS
$ echo "PIPE = "$PIPE
PIPE =
Dlaczego potok uniemożliwia funkcji eksportowanie zmiennej? Czy istnieje sposób, aby to naprawić bez uciekania się do plików tymczasowych lub nazwanych potoków?
Rozwiązany:
Działający kod dzięki Gillesowi:
par_set $(echo $*|tr '=' ' ') > >(sed -e's/^/ /' >> ${LOG})
Umożliwia to wywoływanie skryptu w następujący sposób:
$ . ./script.sh PROCESS_SUB ROCKS PIPELINES=NOGOOD
$ echo $PROCESS_SUB
ROCKS
$ echo $PIPELINES
NOGOOD
$ cat log
7:20140606155622162731431:script.sh:29581:Parse Command Line parameters. Params must be in matched pairs separated by one or more '=' or ' '.
PROCESS_SUB=ROCKS
PIPELINES=NOGOOD
Projekt hostowany na bitbucket https://bitbucket.org/adalby/monitor-bash, jeśli jest zainteresowany pełnym kodem.
To nie działa, ponieważ każda strona potoku działa w podpowłoce w
bash
, a zmienne ustawione w podpowłoce są lokalne dla tej podpowłoki.Aktualizacja:
Wygląda na to, że łatwo jest przekazywać zmienne z rodzica do powłoki potomnej, ale naprawdę trudno to zrobić w drugą stronę. Niektóre obejścia to nazwane potoki, pliki tymczasowe, zapisywanie na standardowe wyjście i czytanie w obiekcie nadrzędnym itp.
Niektóre referencje:
http://mywiki.wooledge.org/BashFAQ/024
https://stackoverflow.com/q/15541321/3565972
https://stackoverflow.com/a/15383353/3565972
http://forums.opensuse.org/showthread .php / 458979-How-export-variable-in-subshell-back-out-to-parent
źródło
$$
jest tak samo dla powłok nadrzędnych i podrzędnych. Możesz użyć,$BASHPID
aby uzyskać pid podpowłoki. Kiedy jestemecho $$ $BASHPID
wpar_set
środku, dostaję różne stawki.Wskazuje się na podpowłoki - które można obejść z pewnym finansowaniem w powłoce poza potokiem - ale trudniejsza część problemu dotyczy współbieżności potoku .
Wszyscy członkowie procesu potoku rozpoczynają się od razu , więc problem może być łatwiejszy do zrozumienia, jeśli spojrzysz na to w ten sposób:
Procesy potokowe nie mogą dziedziczyć wartości zmiennych, ponieważ są one już wyłączone i działają przed ustawieniem zmiennej.
Naprawdę nie rozumiem, jaki jest sens twojej funkcji - jaki cel jej jeszcze nie służy
export
? A może po prostuvar=val
? Na przykład, oto znowu prawie ten sam potok:I z
export
:Więc twoja rzecz może działać jak:
Który zaloguje się na
sed
wyjściu pliku i dostarczy go do twojej funkcji jako split-split"$@"
.Lub alternatywnie:
Gdybym jednak miał napisać twoją funkcję, prawdopodobnie wyglądałby tak:
źródło
|pipeline | sh
sh
. On już używaexport
.