Ich habe die folgende rekursive Funktion zum Festlegen von Umgebungsvariablen:
function par_set {
PAR=$1
VAL=$2
if [ "" != "$1" ]
then
export ${PAR}=${VAL}
echo ${PAR}=${VAL}
shift
shift
par_set $*
fi
}
Wenn ich es selbst aufrufe, setzt es sowohl die Variable als auch das Echo auf stdout:
$ par_set FN WORKS
FN=WORKS
$ echo "FN = "$FN
FN = WORKS
Das Umleiten von stdout in eine Datei funktioniert auch:
$ par_set REDIR WORKS > out
cat out
REDIR=WORKS
$ echo "REDIR = "$REDIR
REDIR = WORKS
Wenn ich jedoch stdout an einen anderen Befehl weitergebe, wird die Variable nicht gesetzt:
$ par_set PIPE FAILS |sed -e's/FAILS/BARFS/'
PIPE=BARFS
$ echo "PIPE = "$PIPE
PIPE =
Warum verhindert die Pipe, dass die Funktion die Variable exportiert? Gibt es eine Möglichkeit, dies zu beheben, ohne auf temporäre Dateien oder Named Pipes zurückzugreifen?
Gelöst:
Arbeitscode dank Gilles:
par_set $(echo $*|tr '=' ' ') > >(sed -e's/^/ /' >> ${LOG})
Dadurch kann das Skript folgendermaßen aufgerufen werden:
$ . ./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 gehostet auf bitbucket https://bitbucket.org/adalby/monitor-bash, wenn Sie an vollständigem Code interessiert sind.
Dies funktioniert nicht, da jede Seite der Pipe in einer Unterschale ausgeführt
bash
wird und die in einer Unterschale festgelegten Variablen lokal für diese Unterschale sind.Aktualisieren:
Es sieht so aus, als ob es einfach ist, Variablen vom übergeordneten Element an die untergeordnete Shell zu übergeben, aber es ist wirklich schwierig, dies andersherum zu tun. Einige Problemumgehungen werden als Pipes, temporäre Dateien, Schreiben in stdout und Lesen im übergeordneten Element usw. bezeichnet.
Einige Referenzen:
http://mywiki.wooledge.org/BashFAQ/024
/programming//q/15541321/3565972
/programming//a/15383353/3565972
http://forums.opensuse.org/showthread .php / 458979-How-Export-Variable-in-Subshell-Back-Out-to-Parent
quelle
$$
ist das gleiche für Eltern- und Kinderschalen. Sie können verwenden$BASHPID
, um die Subshell-PID zu erhalten. Wenn ichecho $$ $BASHPID
innerhalbpar_set
ich verschiedene pids bekommen.Sie weisen auf die Subshells hin, die mit etwas Finagling in der Shell außerhalb einer Pipeline umgangen werden können, aber der schwierigere Teil des Problems hat mit der Parallelität der Pipeline zu tun .
Alle Prozessmitglieder der Pipeline starten gleichzeitig. Daher ist das Problem möglicherweise leichter zu verstehen, wenn Sie es folgendermaßen betrachten:
Die Pipeline-Prozesse können die Variablenwerte nicht erben, da sie bereits deaktiviert sind und ausgeführt werden, bevor die Variable jemals festgelegt wird.
Ich kann nicht wirklich verstehen, worum es bei Ihrer Funktion geht - welchen Zweck erfüllt sie, der
export
noch nicht erfüllt ist? Oder auch nurvar=val
? Hier ist zum Beispiel wieder fast dieselbe Pipeline:Und mit
export
:So könnte dein Ding funktionieren wie:
Dies würde sich bei der
sed
Ausgabe einer Datei anmelden und diese als Shell-Split an Ihre Funktion liefern"$@"
.Oder alternativ:
Wenn ich Ihre Funktion schreiben würde, würde sie wahrscheinlich so aussehen:
quelle
|pipeline | sh
sh
. Er benutzt schonexport
.