Wenn ich prüfe, /proc/1/environ
sehe ich eine durch Null-Bytes getrennte Zeichenfolge der 1
Umgebungsvariablen des Prozesses . Ich möchte diese Variablen in meine aktuelle Umgebung integrieren. Gibt es eine einfache Möglichkeit, dies zu tun?
Die proc
Manpage gibt mir einen Ausschnitt, mit dem sich jede Umgebungsvariable zeilenweise ausdrucken lässt (cat /proc/1/environ; echo) | tr '\000' '\n'
. Dies hilft mir zu überprüfen, ob der Inhalt korrekt ist, aber ich muss diese Variablen wirklich in meine aktuelle Bash-Sitzung einbinden.
Wie mache ich das?
quelle
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ)
, dass Variablen mit Anführungszeichen auch richtig behandelt werden."$@"
statt'{}'
. Für diejenigen, die sich über das--
Argument in seiner verbesserten Antwort wundern : Positionsargumente,bash -c command_string
die ab zugewiesen werden sollen$0
, während"$@"
es um Argumente erweitert wird, die ab beginnen$1
. Das Argument--
wird zugewiesen$0
.In
bash
können Sie Folgendes tun. Dies funktioniert für alle möglichen Inhalte der Variablen und vermeideteval
:Dadurch werden die gelesenen Variablen als Shell-Variablen in der laufenden Shell deklariert. So exportieren Sie die Variablen stattdessen in die aktuelle Shell-Umgebung:
quelle
In dieser Antwort gehe ich von einem System aus, in dem
/proc/$pid/environ
die Umgebung des Prozesses mit der angegebenen PID mit Null-Bytes zwischen Variablendefinitionen zurückgegeben wird. ( Also Linux, Cygwin oder Solaris (?) ).Zsh
(Ziemlich einfach wie zsh: Eine Eingabeumleitung ohne Befehl
<FILE
entsprichtcat FILE
. Die Ausgabe der Befehlssubstitution wird durch Parameter erweitert, wobei die Flagsps:\000:
„Auf null Bytes aufteilen“ und@
„Wenn das Ganze in doppelten Anführungszeichen steht, dann behandeln “ bedeuten jedes Array-Element als separates Feld ”(verallgemeinernd"$@"
).Bash, mksh
(In diesen Shells hat ein leeres Trennzeichen zur Folge,
read
dass Null-Bytes als Trennzeichen verwendet werden. Ich verwende esPWD
als temporären Variablennamen, um zu vermeiden, dass eine andere Variable überladen wird, die möglicherweise importiert wird. Auch wenn Sie sie technisch importieren könnenPWD
, bleibt sie nur bis zum der nächstecd
.)POSIX
Die POSIX-Portabilität ist für diese Frage nicht besonders interessant, da sie nur für Systeme gilt, die über Folgendes verfügen
/proc/PID/environ
. Die Frage ist also, was Solaris sed unterstützt - oder ob Solaris/proc/PID/environ
dies früher getan hat , aber ich bin bei den Solaris-Funktionen weit hinter den Erwartungen zurück, so dass dies heute der Fall sein könnte. Unter Linux sind GNU-Dienstprogramme und BusyBox beide nullsicher, jedoch mit Einschränkungen.Wenn wir auf POSIX-Portabilität bestehen, ist keines der POSIX-Textdienstprogramme für die Verarbeitung von Null-Bytes erforderlich, was schwierig ist. Hier ist eine Lösung, die davon ausgeht, dass awk ein Null-Byte als Datensatzbegrenzer unterstützt (nawk und gawk ebenso wie BusyBox awk, mawk jedoch nicht).
BusyBox awk (die die Version allgemein auf eingebettete Linux Systemen zu finden ist) unterstützen Null - Bytes , aber nicht einstellen ,
RS
um"\0"
in einemBEGIN
Block und die Befehlszeile nicht Syntax oben; es unterstützt jedoch-v 'RS="\0"'
. Ich habe nicht untersucht, warum, das sieht aus wie ein Fehler in meiner Version (Debian wheezy).(Wrap alle
Liniennull getrennte Datensätze in Apostrophe"\047"
, nachdem die einfachen Anführungszeichen innerhalb Werte zu entkommen.)Vorbehalte
Beachten Sie, dass in diesen Fällen möglicherweise versucht wird, schreibgeschützte Variablen festzulegen (wenn Ihre Shell schreibgeschützte Variablen enthält).
quelle
Ich bin damit herumgegangen. Ich war mit der Portabilität von Null-Bytes frustriert. Es war nicht gut für mich, dass es keine zuverlässige Möglichkeit gab, mit ihnen in einer Muschel umzugehen. Also suchte ich weiter. Die Wahrheit ist, dass ich verschiedene Wege gefunden habe, von denen nur einige in meiner anderen Antwort aufgeführt sind. Das Ergebnis waren jedoch mindestens zwei Shell-Funktionen, die folgendermaßen funktionieren:
Zuerst werde ich über die
\0
Abgrenzung sprechen . Das ist eigentlich ganz einfach. Hier ist die Funktion:Nimmt
od
im Grunde genommen jedes Bytestdin
und schreibtstdout
es in hexadezimal eins pro Zeile.Ich wette, Sie können sich vorstellen, welches das ist
\0null
, oder? So geschrieben ist es einfach mit jedem umzugehensed
.sed
Speichert nur die letzten zwei Zeichen in jeder Zeile, bis eine Null gefunden wird. An diesem Punkt werden die Zwischenzeilen durch einen benutzerfreundlichen Formatcode ersetztprintf
und die Zeichenfolge gedruckt. Das Ergebnis ist ein\0null
begrenztes Array von Hex-Byte-Zeichenfolgen. Aussehen:Ich habe das Obige weitergeleitet,
tee
damit Sie sowohl die Ausgabe der Befehlsaufhebung als auch das Ergebnis derprintf
Verarbeitung sehen können. Ich hoffe, Sie werden feststellen, dass die Subshell auch nicht in Anführungszeichen steht, sondernprintf
nur am\0null
Begrenzer geteilt ist. Aussehen:Auch zu dieser Erweiterung gibt es keine Anführungszeichen - es spielt keine Rolle, ob Sie sie zitieren oder nicht. Dies liegt daran, dass die
\n
Bisswerte mit Ausnahme der einen E-Zeile, die jedes Mal generiert wird, wennsed
eine Zeichenfolge gedruckt wird, nicht getrennt durchlaufen werden . Wortteilung gilt nicht. Und das macht es möglich:Die obige Funktion verwendet
_zedlmt
entweder${pcat}
einen vorbereiteten Strom von Byte-Code für das Beschaffen von Umgebungen für einen beliebigen Prozess, der sich in der aktuellen Shell befindet, oder/proc
direkt.dot
${psrc}
denselben oder ohne Parameter, um eine verarbeitete Ausgabe desselben für das Terminal anzuzeigenset
oderprintenv
wird. Alles was Sie brauchen ist eine$pid
- jede lesbare/proc/$pid/environ
Datei reicht aus.Du benutzt es so:
Aber was ist der Unterschied zwischen menschenfreundlich und säuerlich ? Nun, der Unterschied besteht darin, was diese Antwort anders macht als alle anderen hier - einschließlich meiner anderen. Jede andere Antwort hängt davon ab, dass die Shell auf die eine oder andere Weise zitiert, um alle Randfälle zu behandeln. Es funktioniert einfach nicht so gut. Bitte glauben Sie mir - ich habe es versucht. Aussehen:
KEINE Menge von unkonventionellen Zeichen oder Anführungszeichen kann dies stören, da die Bytes für jeden Wert erst ausgewertet werden, wenn der Inhalt in dem Moment bezogen wird, in dem er stammt. Und wir wissen bereits, dass es mindestens einmal als Wert funktioniert hat - hier ist kein Parsen oder Anführungszeichen erforderlich, da dies eine byteweise Kopie des ursprünglichen Werts ist.
Die Funktion wertet zuerst die
$var
Namen aus und wartet, bis die Überprüfungen abgeschlossen sind, bevor.dot
das hier angegebene Dokument in Dateideskriptor 3 eingespeist wird. Es ist narrensicher. Und POSIX portabel. Nun, zumindest die \ 0null-Behandlung ist POSIX-portierbar - das / process-Dateisystem ist offensichtlich Linux-spezifisch. Und deshalb gibt es zwei Funktionen.quelle
Verwendung
source
und Prozessersetzung :Kurz:
Verwenden
eval
und Ersetzen von Befehlen :Der
sed
Anruf kann durch einenawk
Anruf ersetzt werden:Vergessen Sie jedoch nicht, dass keine Umgebungsvariablen gelöscht werden, die nicht in PID 1 enthalten sind.
quelle
Es ist zu beachten, dass Prozesse Umgebungsvariablen haben können, die keine gültigen Bash / Sh / * sh-Variablen sind - POSIX empfiehlt, erfordert jedoch nicht, dass Umgebungsvariablen übereinstimmende Namen haben
^[a-zA-Z0-9_][a-zA-Z0-9_]*$
.So erstellen Sie in Bash eine Liste von Variablen, die mit der Shell einer anderen Prozessumgebung kompatibel sind:
Ebenso, um sie zu laden:
Dieses Problem tritt nur gelegentlich auf, aber wenn es auftritt ...
quelle
Ich denke das ist POSIX portable:
Aber @Gilles macht einen guten Punkt -
sed
wird wahrscheinlich mit Nullen umgehen, aber vielleicht auch nicht. Also gibt es diese (ich denke wirklich, diesmal) tatsächlich auch tragbare POSIX-Methode:Wenn Sie jedoch GNU haben
sed
, müssen Sie nur Folgendes tun:Nun, POSIX Portable ist bis auf das,
/dev/...
was nicht spezifiziert ist, aber Sie können erwarten, dass sich diese Syntax auf den meisten Unices gleich verhält.Wenn dies irgendetwas mit Ihrer anderen Frage zu tun hat, möchten Sie sie vielleicht so verwenden:
Das Here-Doc ist äußerst hilfreich, da es verhindert, dass die Shell mit einem der Zitate, mit denen wir in der Subshell so hart arbeiten, in Konflikt gerät, und uns außerdem einen zuverlässigen Pfad zu einer
.dot
Sourcing- Datei und nicht zu einer Subshell oder einer Shell bietet Variable. Andere verwenden hier den<(process substitution)
Bashismus, der auf die gleiche Weise funktioniert - nur ist er definitiv anonym,|pipe
während POSIX nur einen Wertiohere
für here-docs angibt und daher jede Art von Datei sein kann, obwohl es in der Praxis normalerweise einetemp
Datei ist. (dash,
verwendet jedoch anonym|pipes
für here-docs) . Das Unglückliche an der Prozessersetzung ist jedoch, dass sie auch von der Shell abhängt - was besonders ärgerlich sein kann, wenn Sie damit arbeiteninit
.Das funktioniert
|pipes
natürlich auch mit , aber dann verliert man am Ende die Umwelt wieder, wenn der|pipe's
Zustand mit seiner Unterschale verdunstet. Das funktioniert dann wieder:Die
sed
Anweisung selbst hält jede Zeile im Speicher, bis die letzte erreicht ist. Zu diesem Zeitpunkt führt sie eine globale Ersetzungsbehandlung durch, bei der Anführungszeichen gesetzt und gegebenenfalls neue Zeilen eingefügt werden, indem die Nullen verankert werden. Ziemlich einfach.Auf dem
dash
Bild sehen Sie, dass ich mich dafür entschieden habe, das \ mess zu vermeiden, und dieGNU
spezifische-r
Option hinzugefügt habesed
. Aber das ist nur, weil es weniger zu tippen war. Es funktioniert so oder so, wie Sie imzsh
Bild sehen können.Hier ist
zsh
:Und hier machen
dash
wir das Gleiche:Sogar Fluchtterminals bleiben unversehrt:
quelle
/proc/PID/environ
. Die Frage ist also, was Solaris sed unterstützt - oder ob Solaris dies bisher/proc/PID/environ
nicht getan hat , aber ich bin es.) hinter der Kurve auf Solaris-Funktionen, so könnte es heutzutage.)sed
jedoch benötigt, um ASCII-Hexadezimalwerte zu verarbeiten, von denen das Nullbyte eins ist. Außerdem dachte ich eigentlich nur, ob das noch viel einfacher geht.\xNN
Übrigens ist die Syntax in POSIX nicht erforderlich, nicht einmal die\OOO
Oktalsyntax (in C-Strings und in awk, ja, aber nicht in sed-Regexps)./proc/PID/environ
(es hat mehrere andere Linux-ähnliche Einträge/proc/PID
, aber nichtenviron
). Eine tragbare Lösung muss also nicht über Linux-Tools hinausgehen, dh GNU sed oder BusyBox sed. Beide unterstützen\x00
reguläre Ausdrücke, sodass Ihr Code so portabel wie nötig ist (jedoch nicht POSIX). Es ist jedoch zu komplex.quelle