GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie man Umgebungsvariablen eines Prozesses liest

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

Wenn sich ein Prozess ändert seine Umgebung, dann müssen Sie, um die Umgebung zu lesen, die Symboltabelle für den Prozess haben und den ptrace verwenden Systemaufruf (zum Beispiel mit gdb ), um die Umgebung aus dem globalen char **__environ zu lesen Variable. Es gibt keine andere Möglichkeit, den Wert einer Variablen von einem laufenden Linux-Prozess abzurufen.

Das ist die Antwort. Nun zu einigen Anmerkungen.

Das Obige geht davon aus, dass der Prozess POSIX-kompatibel ist, was bedeutet, dass der Prozess seine Umgebung mit einer globalen Variable char **__environ verwaltet wie in der Ref Spec angegeben.

Die anfängliche Umgebung für einen Prozess wird dem Prozess in einem Puffer fester Länge auf dem Stack des Prozesses übergeben. (Der übliche Mechanismus, der dies tut, ist 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 anfängliche Umgebung erforderliche Größe, können Sie keine neuen Variablen hinzufügen, ohne vorhandene Variablen zu löschen oder den Stapel zu zerstören. Daher würde jedes vernünftige Schema, um Änderungen in der Umgebung eines Prozesses zuzulassen, den Heap verwenden, wo Speicher in beliebiger Größe zugewiesen und freigegeben werden kann, was genau das ist, was GNU libc tut (glibc ) für Sie erledigt.

Wenn der Prozess glibc verwendet , dann ist es POSIX-kompatibel, mit __environ in glibc//posix/environ.c deklariert werden Glibc initialisiert __environ mit einem Zeiger auf den Speicher, der malloc ist s vom Heap des Prozesses und kopiert dann die anfängliche Umgebung vom Stack in diesen Heap-Bereich. Jedes Mal, wenn der Prozess den setenv verwendet Funktion, glibc macht einen realloc um die Größe des Bereichs anzupassen, der __environ zeigt auf, 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-Klon git://git.sv.gnu.org/hurd/hurd.git hurd).

Wenn der neue Prozess jetzt nur fork ist ed, ohne ein nachfolgendes exec Überschreiben des Stacks, dann wird das Kopieren von Argumenten und Umgebungen in linux//kernel/fork.c:do_fork(...) durchgeführt , wobei copy_process Routine ruft dup_task_struct auf das den Stack des neuen Prozesses allokiert, indem es alloc_thread_info_node aufruft , die setup_thread_stack aufruft (linux//include/linux/sched.h ) für den neuen Prozess mit alloc_thread_info_node .

Schließlich der POSIX __environ Konvention ist ein Benutzerbereich Konvention. Es hat keine Verbindung mit irgendetwas im Linux-Kernel. Sie können ein Userspace-Programm schreiben, ohne glibc zu verwenden und ohne __environ global und verwalten Sie dann die Umgebungsvariablen nach Belieben. Niemand wird Sie dafür verhaften, aber Sie müssen Ihre eigenen Umgebungsverwaltungsfunktionen schreiben (setenv /getenv ) und eigene Wrapper für sys_exec und es ist wahrscheinlich, dass niemand erraten kann, wo Sie die Änderungen an Ihrer Umgebung vorgenommen haben.


/proc/$pid/environ wird aktualisiert, wenn der Prozess seine eigene Umgebung ändert. Aber viele Programme machen sich nicht die Mühe, ihre eigene Umgebung zu ändern, weil es ein bisschen sinnlos ist:Die Umgebung eines Programms ist nicht durch normale Kanäle sichtbar, nur durch /proc und ps , und sogar nicht jede Unix-Variante hat diese Art von Feature, also verlassen sich Anwendungen nicht darauf.

Was den Kernel betrifft, erscheint die Umgebung nur als Argument von execve Systemaufruf, der das Programm startet. Linux legt einen Bereich im Speicher durch /proc offen , 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, wäre es unmöglich, neue Variablen hinzuzufügen oder die Länge eines Werts zu ändern.


Sie wird aktualisiert, sobald der Prozess seine Umgebungsvariablen erfasst/löscht. Haben Sie eine Referenz, die den environ angibt Datei wird für den Prozess in ihrem Prozessverzeichnis unter /proc filesystem nicht aktualisiert?

xargs --null --max-args=1 echo < /proc/self/environ

oder

xargs --null --max-args=1 echo < /proc/<pid>/environ

oder

ps e -p <pid>

Das obige gibt die Umgebungsvariablen des Prozesses in ps aus Ausgabeformat, 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> 

BEARBEITEN: /proc/pid/environ wird nicht aktualisiert! Ich stehe korrigiert. Der Überprüfungsprozess ist unten. Die untergeordneten Elemente, von denen der Prozess geforkt wird, erben jedoch die Prozessumgebungsvariable und sie ist in ihrer jeweiligen /proc/self/environ-Datei sichtbar. (Strings verwenden)

Mit in der Shell:Hier ist xargs ein untergeordneter Prozess und erbt daher die Umgebungsvariable und spiegelt sich auch in ihrem /proc/self/environ wider 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üfung von einer anderen Sitzung aus, wo das Terminal/die Sitzung nicht der untergeordnete Prozess der Shell ist, in der die Umgebungsvariable gesetzt ist.

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

terminal1: :Beachten Sie, dass printenv gegabelt wird 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 gesetzt wurde, 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] ~]$ 

Linux
  1. So setzen/erstellen Sie Umgebungs- und Shell-Variablen in Linux

  2. So übergeben Sie Umgebungsvariablen an Docker-Container

  3. So setzen, listen und entfernen Sie Umgebungsvariablen in Linux

  4. Wie kann ich R dazu bringen, meine Umgebungsvariablen zu lesen?

  5. So setzen Sie Linux-Umgebungsvariablen mit Ansible

So legen Sie die Umgebungsvariable in Windows fest

So legen Sie Umgebungsvariablen in MacOS fest

So setzen und listen Sie Umgebungsvariablen in Linux auf

So setzen und listen Sie Umgebungsvariablen in Linux auf

So setzen und löschen Sie Umgebungsvariablen unter Linux

Linux-Umgebungsvariablen