Linux /proc/<pid>/environ
wird nicht aktualisiert (soweit ich weiß, enthält die Datei die ursprüngliche Umgebung des Prozesses).
Wie kann ich die aktuelle Umgebung eines Prozesses lesen ?
quelle
Linux /proc/<pid>/environ
wird nicht aktualisiert (soweit ich weiß, enthält die Datei die ursprüngliche Umgebung des Prozesses).
Wie kann ich die aktuelle Umgebung eines Prozesses lesen ?
/proc/$pid/environ
wird aktualisiert, wenn der Prozess seine eigene Umgebung ändert. Viele Programme machen sich jedoch nicht die Mühe, ihre eigene Umgebung zu ändern, da dies etwas sinnlos ist: Die Umgebung eines Programms ist nicht über normale Kanäle sichtbar, sondern nur über /proc
und ps
, und nicht jede Unix-Variante verfügt über diese Funktion, sodass Anwendungen nicht darauf angewiesen sind darauf.
Für den Kernel erscheint die Umgebung nur als Argument des execve
Systemaufrufs, der das Programm startet. Linux macht einen Bereich im Arbeitsspeicher durch verfügbar /proc
, und einige Programme aktualisieren diesen Bereich, während andere dies nicht tun. Insbesondere glaube ich nicht, dass eine Shell diesen Bereich aktualisiert. Da der Bereich eine feste Größe hat, ist es unmöglich, neue Variablen hinzuzufügen oder die Länge eines Werts zu ändern.
PATH=foo
in eine Shell schreiben, heißt das noch lange nicht, dass die Shell geändert wird*envp
. In einigen Shells wurde nur eine interne Datenstruktur aktualisiert, und es wird der externe Programmausführungscode aktualisiert*envp
. Schauen Sie sichassign_in_env
invariables.c
in der Bash - Quelle, zum Beispiel.fork
densys_fork
Aufruf unter Verwendung der Heap-zugewiesenen Umgebung für den untergeordneten Prozess durch.argv
sind häufiger, aber beide sind vorhanden).Sie können die ursprüngliche Umgebung eines Prozesses aus lesen
/proc/<pid>/environ
.Wenn ein Prozess seine Umgebung ändert , müssen Sie zum Lesen der Umgebung über die Symboltabelle für den Prozess verfügen und den
ptrace
Systemaufruf (z. B. mithilfe vongdb
) verwenden, um die Umgebung aus der globalenchar **__environ
Variablen zu lesen . Es gibt keine andere Möglichkeit, den Wert einer Variablen aus einem laufenden Linux-Prozess abzurufen.Das ist die Antwort. Nun zu einigen Notizen.
Bei den obigen Ausführungen wird davon ausgegangen, dass der Prozess POSIX-kompatibel ist. Dies bedeutet, dass der Prozess seine Umgebung mithilfe einer globalen Variablen verwaltet
char **__environ
, die in der Referenzspezifikation angegeben ist .Die ursprüngliche Umgebung für einen Prozess wird in einem Puffer fester Länge auf dem Prozessstapel an den Prozess übergeben. (Der übliche Mechanismus hierfür ist der folgende
linux//fs/exec.c:do_execve_common(...)
.) Da die Größe des Puffers so berechnet wird, dass sie nicht größer ist als die für die ursprüngliche Umgebung erforderliche Größe, können Sie keine neuen Variablen hinzufügen, ohne vorhandene Variablen zu löschen oder den Stapel zu zerschlagen. Jedes vernünftige Schema, um Änderungen in der Umgebung eines Prozesses zuzulassen, würde den Heap verwenden, in dem Speicher in beliebigen Größen zugewiesen und freigegeben werden kann. Genau das macht GNUlibc
(glibc
) für Sie.Wenn der Prozess verwendet
glibc
, ist er POSIX-kompatibel. Wenn__environ
er inglibc//posix/environ.c
Glibc deklariert wird, wird er__environ
mit einem Zeiger auf den Speicher initialisiert , dermalloc
aus dem Heap des Prozesses stammt. Anschließend wird die ursprüngliche Umgebung vom Stapel in diesen Heapbereich kopiert. Jedes Mal, wenn der Prozess diesetenv
Funktion verwendet,glibc
wird a ausgeführtrealloc
, um die Größe des Bereichs anzupassen, auf den__environ
der neue Wert oder die neue Variable verweist. (Sie können den glibc-Quellcode mit herunterladengit clone git://sourceware.org/git/glibc.git glibc
). Um den Mechanismus wirklich zu verstehen, müssen Sie auch den Hurd-Code einlesenhurd//init/init.c:frob_kernel_process()
(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).Wenn der neue Prozess nur
fork
bearbeitet wird, ohneexec
den Stapel anschließend zu überschreiben, wird das Argument und die Umgebung kopiert. Dabei ruftlinux//kernel/fork.c:do_fork(...)
diecopy_process
Routine aufdup_task_struct
, die den Stapel des neuen Prozesses durch Aufrufen vonalloc_thread_info_node
aufruftsetup_thread_stack
(linux//include/linux/sched.h
) für den neuen Prozess mitalloc_thread_info_node
.Schließlich ist die POSIX-
__environ
Konvention eine User-Space- Konvention. Es hat keine Verbindung mit irgendetwas im Linux-Kernel. Sie können ein Userspace-Programm ohneglibc
und ohne das__environ
Globale schreiben und dann die Umgebungsvariablen verwalten, wie Sie möchten. Niemand wird Sie dafür verhaften, aber Sie müssen Ihre eigenen Umgebungsverwaltungsfunktionen (setenv
/getenv
) und Ihre eigenen Wrapper dafür schreiben,sys_exec
und es ist wahrscheinlich, dass niemand ahnen kann, wo Sie die Änderungen an Ihrer Umgebung vorgenommen haben.quelle
/proc/[pid]/
scheinen eine seltsame Kodierung zu haben (jemand anderes weiß möglicherweise, was und warum). Für michcat environ
würde man einfach die Umgebungsvariablen in einem wirklich schwer lesbaren Format ausdrucken.cat environ | strings
löste das für mich.Es wird aktualisiert, wenn der Prozess seine Umgebungsvariablen erfasst / löscht. Haben Sie eine Referenz, die besagt, dass die
environ
Datei für den Prozess in ihrem Prozessverzeichnis unter / proc Dateisystem nicht aktualisiert wurde?oder
oder
Mit dem obigen Befehl werden die Umgebungsvariablen des Prozesses im
ps
Ausgabeformat gedruckt. Eine Textverarbeitung (Parsen / Filtern) ist erforderlich, um die Umgebungsvariablen als Liste anzuzeigen.Solaris (nicht gefragt, aber als Referenz werde ich hier posten):
oder
EDIT: / proc / pid / environ wird nicht aktualisiert! Ich stehe korrigiert. Überprüfungsprozess ist unten. Die untergeordneten Elemente, von denen der Prozess abgeleitet wurde, erben jedoch die Prozessumgebungsvariable und diese wird in der jeweiligen Datei / proc / self / environ angezeigt. (Benutze Strings)
Mit in der Shell: Hier ist xargs ein untergeordneter Prozess und erbt daher die Umgebungsvariable und spiegelt sich auch in seiner
/proc/self/environ
Datei wider .Überprüfung aus einer anderen Sitzung, in der das Terminal / die Sitzung nicht der untergeordnete Prozess der Shell ist, in der die Umgebungsvariable festgelegt ist.
Überprüfung von einem anderen Terminal / einer anderen Sitzung auf demselben Host:
terminal1 :: Beachten Sie, dass printenv fork'd und ein untergeordneter Prozess von bash ist und daher seine eigene Umgebungsdatei liest.
terminal2: auf demselben Host - starten Sie es nicht in derselben Shell, in der die obige Variable festgelegt wurde, sondern starten Sie das Terminal separat.
quelle
export foo=bar
in der einen Bash-Sitzung (pid xxxx), dann mache ichcat /proc/xxxx/environ | tr \\0 \\n
in der anderen Bash-Sitzung und ich sehe nichtfoo
.gdb
an die PID angehängt ist, aber immer noch keinen Hinweis darauf. Der Block der Umgebungsvariablen im Speicher wird bei jeder Änderung neu zugeordnet und spiegelt sich nicht in der Umgebungsdatei des eigenen Prozesses im proc-Dateisystem wider, kann jedoch vom untergeordneten Prozess geerbt werden. Dies bedeutet, dass es einfacher sein kann, die eigentlichen Details zu kennen, wenn die Verzweigung auftritt und wie der untergeordnete Prozess Umgebungsvariablen unverändert kopiert.Nun, das Folgende hängt nicht mit den wahren Absichten des Autors zusammen, aber wenn Sie das wirklich "LESEN" wollen
/proc/<pid>/environ
, können Sie es versuchenwas ist besser als
cat
es.quelle
strings
. Halte es einfach.xargs --null
.tr '\0' '\n' < /proc/$$/environ | ...