it-swarm.com.de

Lesen von Umgebungsvariablen eines Prozesses

Linux /proc/<pid>/environ wird nicht aktualisiert (so wie ich es verstehe, enthält die Datei die ursprüngliche Umgebung des Prozesses).

Wie kann ich die aktuelle Umgebung eines Prozesses lesen?

45
user14284

/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 selbst nicht jede Unix-Variante verfügt über diese Funktion, sodass sich Anwendungen nicht darauf verlassen.

Für den Kernel wird die Umgebung nur als Argument des Systemaufrufs execve angezeigt, mit dem das Programm gestartet wird. Linux macht einen Speicherbereich durch /proc, und einige Programme aktualisieren diesen Bereich, andere nicht. Insbesondere glaube ich nicht, dass 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.

Sie können die anfängliche Umgebung eines Prozesses aus /proc/<pid>/environ lesen.

Wenn ein Prozess seine Umgebung ändert , müssen Sie zum Lesen der Umgebung die Symboltabelle für den Prozess haben und beispielsweise den Systemaufruf ptrace verwenden indem Sie gdb) verwenden, um die Umgebung aus der globalen Variablen char **__environ 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.

Oben wird davon ausgegangen, dass der Prozess POSIX-kompatibel ist. Dies bedeutet, dass der Prozess seine Umgebung mithilfe einer globalen Variablen char **__environ verwaltet, wie in der Referenzspezifikation angegeben.

Die anfä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 linux//fs/exec.c:do_execve_common(...).) Da die Größe des Puffers so berechnet wird, dass sie nicht größer als die für die ursprüngliche Umgebung erforderliche Größe ist, können Sie keine neuen Variablen hinzufügen, ohne vorhandene Variablen oder zu löschen den Stapel 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 tut GNU libc (glibc)) für Sie.

Wenn der Prozess glibc verwendet, ist er POSIX-kompatibel, wobei __environ in glibc//posix/environ.c deklariert wird. Glibc initialisiert __environ mit einem Zeiger auf den Speicher, den er mallocs aus dem Heap des Prozesses erstellt, und kopiert dann die ursprüngliche Umgebung vom Stapel in diesen Heap-Bereich. Jedes Mal, wenn der Prozess die Funktion setenv verwendet, führt glibc einen realloc aus, um die Größe des Bereichs anzupassen, auf den __environ zeigt, um den neuen Wert oder die neue Variable aufzunehmen. (Sie können den glibc-Quellcode mit git clone git://sourceware.org/git/glibc.git glibc herunterladen.) Um den Mechanismus wirklich zu verstehen, müssen Sie auch den Hurd-Code in hurd//init/init.c:frob_kernel_process() lesen (git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).

Wenn der neue Prozess nur forked ist, ohne dass ein nachfolgender exec den Stack überschreibt, erfolgt das Kopieren von Argumenten und Umgebungen in linux//kernel/fork.c:do_fork(...), wo die Routine copy_processdup_task_struct aufruft, der den Stack des neuen Prozesses durch Aufrufen von alloc_thread_info_node zuweist , der setup_thread_stack (linux//include/linux/sched.h) für den neuen Prozess mit alloc_thread_info_node aufruft.

Schließlich ist die POSIX __environ Konvention eine User-Space Konvention. Es hat keine Verbindung zu irgendetwas im Linux-Kernel. Sie können ein Userspace-Programm schreiben, ohne glibc und ohne __environ global zu verwenden, 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 für sys_exec schreiben, und es ist wahrscheinlich, dass niemand erraten kann, wo Sie die Änderungen an Ihrer Umgebung vorgenommen haben .

41

Es wird aktualisiert, sobald der Prozess seine Umgebungsvariablen erfasst/löscht. Haben Sie eine Referenz, die besagt, dass die Datei environ für den Prozess in ihrem Prozessverzeichnis unter/proc filesystem 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 Ausgabeformat ps gedruckt. Die 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. Der Überprüfungsprozess ist unten. Die untergeordneten Elemente, von denen der Prozess gegabelt wird, erben jedoch die Prozessumgebungsvariable und sie ist in ihrer jeweiligen Datei/proc/self/environ sichtbar. (Verwenden Sie Zeichenfolgen)

Mit in der Shell: Hier ist xargs ein untergeordneter Prozess und erbt daher die Umgebungsvariable und spiegelt sich auch in ihrem /proc/self/environ Datei.

[[email protected] t]$ printenv  | grep MASK
[[email protected] t]$ export MASK=NIKHIL
[[email protected] t]$ printenv  | grep MASK
MASK=NIKHIL
[[email protected] t]$ xargs --null --max-args=1 echo < /proc/self/environ  | grep MASK
MASK=NIKHIL
[[email protected] t]$ unset MASK
[[email protected] t]$ printenv  | grep MASK
[[email protected] t]$ xargs --null --max-args=1 echo < /proc/self/environ  | grep MASK
[[email protected] t]$

Überprüfen von einer anderen Sitzung, in der das Terminal/die Sitzung nicht der untergeordnete Prozess der Shell ist, in der die Umgebungsvariable festgelegt ist.

Überprüfen von einem anderen Terminal/einer anderen Sitzung auf demselben Host:

terminal1 :: Beachten Sie, dass printenv gegabelt ist und ein untergeordneter Prozess von bash ist und daher seine eigene Umgebungsdatei liest.

[[email protected] t]$ echo $$
2610
[[email protected] t]$ export SPIDEY=NIKHIL
[[email protected] t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[[email protected] 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.

[[email protected] ~]$ echo $$
4436
[[email protected] ~]$ xargs --null --max-args=1 echo < /proc/self/environ | grep -i spidey
[[email protected] ~]$ strings -f /proc/2610/environ | grep -i spidey
[[email protected] ~]$ xargs --null --max-args=1 echo < /proc/2610/environ | grep -i spidey
[[email protected] ~]$ 
22
Nikhil Mulley

Nun, das Folgende hängt nicht mit den wirklichen Absichten des Autors zusammen, aber wenn Sie den /proc/<pid>/environ Wirklich "LESEN" möchten, können Sie es versuchen

strings /proc/<pid>/environ

das ist besser als cat es.

8
fibonacci