GNU/Linux >> Tutoriels Linux >  >> Linux

Comment lire les variables d'environnement d'un processus

Vous pouvez lire l'initiale environnement d'un processus de /proc/<pid>/environ .

Si un processus change son environnement, alors pour lire l'environnement vous devez avoir la table des symboles du processus et utiliser le ptrace appel système (par exemple en utilisant gdb ) pour lire l'environnement à partir du char **__environ global variable. Il n'y a pas d'autre moyen d'obtenir la valeur d'une variable à partir d'un processus Linux en cours d'exécution.

C'est la réponse. Maintenant quelques notes.

Ce qui précède suppose que le processus est conforme à POSIX, ce qui signifie que le processus gère son environnement à l'aide d'une variable globale char **__environ comme spécifié dans la réf.

L'environnement initial d'un processus est transmis au processus dans un tampon de longueur fixe sur la pile du processus. (Le mécanisme habituel qui fait cela est linux//fs/exec.c:do_execve_common(...) .) Étant donné que la taille du tampon est calculée pour ne pas dépasser la taille requise pour l'environnement initial, vous ne pouvez pas ajouter de nouvelles variables sans effacer les variables existantes ou briser la pile. Ainsi, tout schéma raisonnable permettant des modifications dans l'environnement d'un processus utiliserait le tas, où la mémoire de tailles arbitraires peut être allouée et libérée, ce qui est exactement ce que GNU libc (glibc ) fait pour vous.

Si le processus utilise glibc , alors il est compatible POSIX, avec __environ étant déclaré en glibc//posix/environ.c Glibc initialise __environ avec un pointeur vers la mémoire qu'il malloc s du tas du processus, puis copie l'environnement initial de la pile dans cette zone de tas. Chaque fois que le processus utilise le setenv fonction, glibc fait un realloc pour ajuster la taille de la zone __environ pointe vers pour accueillir la nouvelle valeur ou variable. (Vous pouvez télécharger le code source de la glibc avec git clone git://sourceware.org/git/glibc.git glibc ). Pour bien comprendre le mécanisme vous devrez également lire le code Hurd en hurd//init/init.c:frob_kernel_process() (git clone git://git.sv.gnu.org/hurd/hurd.git hurd).

Maintenant, si le nouveau processus est seulement fork ed, sans un exec suivant écraser la pile, puis la magie de copie des arguments et de l'environnement se fait dans linux//kernel/fork.c:do_fork(...) , où le copy_process appels de routine dup_task_struct qui alloue la pile du nouveau processus en appelant alloc_thread_info_node , qui appelle setup_thread_stack (linux//include/linux/sched.h ) pour le nouveau processus utilisant alloc_thread_info_node .

Enfin, le POSIX __environ convention est un espace utilisateur convention. Il n'a aucun lien avec quoi que ce soit dans le noyau Linux. Vous pouvez écrire un programme en espace utilisateur sans utiliser glibc et sans le __environ global, puis gérez les variables d'environnement comme bon vous semble. Personne ne vous arrêtera pour cela mais vous devrez écrire vos propres fonctions de gestion de l'environnement (setenv /getenv ) et vos propres wrappers pour sys_exec et il est probable que personne ne pourra deviner où vous placez les changements dans votre environnement.


/proc/$pid/environ se met à jour si le processus modifie son propre environnement. Mais de nombreux programmes ne prennent pas la peine de changer leur propre environnement, car c'est un peu inutile :l'environnement d'un programme n'est pas visible via les canaux normaux, uniquement via /proc et ps , et même toutes les variantes d'Unix ne disposent pas de ce type de fonctionnalité, les applications n'en dépendent donc pas.

En ce qui concerne le noyau, l'environnement n'apparaît que comme argument du execve appel système qui lance le programme. Linux expose une zone en mémoire via /proc , et certains programmes mettent à jour cette zone tandis que d'autres ne le font pas. En particulier, je ne pense pas qu'un shell mette à jour ce domaine. Comme la zone a une taille fixe, il serait impossible d'ajouter de nouvelles variables ou de modifier la longueur d'une valeur.


Il est mis à jour au fur et à mesure que le processus acquiert/supprime ses variables d'environnement. Avez-vous une référence qui indique le environ le fichier n'est pas mis à jour pour le processus dans son répertoire de processus sous /proc filesystem ?

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

ou

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

ou

ps e -p <pid>

Ce qui précède imprimera les variables d'environnement du processus dans le ps format de sortie, le traitement de texte (analyse/filtrage) est nécessaire pour voir les variables d'environnement sous forme de liste.

Solaris (pas demandé, mais pour référence, je posterai ici):

/usr/ucb/ps -wwwe <pid>

ou

pargs -e <pid> 

MODIF : /proc/pid/environ n'est pas mis à jour ! Je me suis trompé. Le processus de vérification est ci-dessous. Cependant, les enfants à partir desquels le processus est dérivé héritent de la variable d'environnement de processus et celle-ci est visible dans leur fichier /proc/self/environ respectif. (Utilisez des chaînes)

Avec dans le shell :ici xargs est un processus enfant et hérite donc de la variable d'environnement et se reflète également dans son /proc/self/environ fichier.

[[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]$

Vérification depuis une autre session, où le terminal/session n'est pas le processus enfant du shell où la variable d'environnement est définie.

Vérification depuis un autre terminal/session sur le même hôte :

terminal1 : :Notez que printenv est fork'd et est un processus enfant de bash et donc il lit son propre fichier environ.

[[email protected] t]$ echo $$
2610
[[email protected] t]$ export SPIDEY=NIKHIL
[[email protected] t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[[email protected] t]$ 

terminal2 : sur le même hôte - ne le lancez pas dans le même shell où la variable ci-dessus a été définie, lancez le terminal séparément.

[[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. Comment définir, répertorier et supprimer des variables d'environnement sous Linux

  2. Comment donnez-vous à su les variables d'environnement utilisateur actuelles

  3. Comment faire en sorte que R lise mes variables d'environnement ?

  4. Comment définir des variables d'environnement Linux avec Ansible

  5. Comment imprimer des variables d'environnement apparemment cachées ?

Comment définir une variable d'environnement dans Windows

Comment définir des variables d'environnement dans MacOS

Comment définir et répertorier les variables d'environnement sous Linux

Comment définir et répertorier les variables d'environnement sous Linux

Comment définir et supprimer des variables d'environnement sous Linux

Variables d'environnement Linux