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 ?
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 ?
Antworten:
/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 sich assign_in_env
in variables.c
in der Bash - Quelle, zum Beispiel.
fork
den sys_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 von gdb
) verwenden, um die Umgebung aus der globalen char **__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 GNU libc
( glibc
) für Sie.
Wenn der Prozess verwendet glibc
, ist er POSIX-kompatibel. Wenn __environ
er in glibc//posix/environ.c
Glibc deklariert wird, wird er __environ
mit einem Zeiger auf den Speicher initialisiert , der malloc
aus dem Heap des Prozesses stammt. Anschließend wird die ursprüngliche Umgebung vom Stapel in diesen Heapbereich kopiert. Jedes Mal, wenn der Prozess die setenv
Funktion verwendet, glibc
wird a ausgeführt realloc
, 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 herunterladen git clone git://sourceware.org/git/glibc.git glibc
). Um den Mechanismus wirklich zu verstehen, müssen Sie auch den Hurd-Code einlesen hurd//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, ohne exec
den Stapel anschließend zu überschreiben, wird das Argument und die Umgebung kopiert. Dabei ruft linux//kernel/fork.c:do_fork(...)
die copy_process
Routine auf dup_task_struct
, die den Stapel des neuen Prozesses durch Aufrufen von alloc_thread_info_node
aufruft setup_thread_stack
( linux//include/linux/sched.h
) für den neuen Prozess mit alloc_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 ohne glibc
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.
/proc/[pid]/
scheinen eine seltsame Kodierung zu haben (jemand anderes weiß möglicherweise, was und warum). Für mich cat 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?
xargs --null --max-args=1 echo < /proc/self/environ
oder
xargs --null --max-args=1 echo < /proc/<pid>/environ
oder
ps e -p <pid>
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):
/usr/ucb/ps -wwwe <pid>
oder
pargs -e <pid>
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 .
[centos@centos t]$ printenv | grep MASK
[centos@centos t]$ export MASK=NIKHIL
[centos@centos t]$ printenv | grep MASK
MASK=NIKHIL
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
MASK=NIKHIL
[centos@centos t]$ unset MASK
[centos@centos t]$ printenv | grep MASK
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
[centos@centos t]$
Ü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.
[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$
terminal2: auf demselben Host - starten Sie es nicht in derselben Shell, in der die obige Variable festgelegt wurde, sondern starten Sie das Terminal separat.
[centos@centos ~]$ echo $$
4436
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/self/environ | grep -i spidey
[centos@centos ~]$ strings -f /proc/2610/environ | grep -i spidey
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/2610/environ | grep -i spidey
[centos@centos ~]$
export foo=bar
in der einen Bash-Sitzung (pid xxxx), dann mache ich cat /proc/xxxx/environ | tr \\0 \\n
in der anderen Bash-Sitzung und ich sehe nicht foo
.
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 versuchen
strings /proc/<pid>/environ
was ist besser als cat
es.
strings
. Halte es einfach.
xargs --null
.
tr '\0' '\n' < /proc/$$/environ | ...