Linux /proc/<pid>/environ
ne met pas à jour (si j'ai bien compris, le fichier contient l'environnement initial du processus).
Comment lire l' environnement actuel d' un processus ?
Linux /proc/<pid>/environ
ne met pas à jour (si j'ai bien compris, le fichier contient l'environnement initial du processus).
Comment lire l' environnement actuel d' un processus ?
Réponses:
/proc/$pid/environ
met à jour si le processus change son propre environnement. Mais de nombreux programmes ne prennent pas la peine de changer leur propre environnement, car il est un peu inutile: l'environnement d'un programme ne sont pas visibles par les voies normales, que par /proc
et ps
, et même pas toutes les variantes unix a ce genre de fonction, afin que les applications ne reposent pas dessus.
En ce qui concerne le noyau, l'environnement n'apparaît que comme l'argument de l' execve
appel système qui lance le programme. Linux expose une zone en mémoire /proc
, et certains programmes la mettent à jour alors 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.
PATH=foo
dans un shell que celui-ci va être modifié *envp
. Dans certains shells, seule la structure de données interne est mise à jour et le code d'exécution du programme externe est mis à jour *envp
. Regardez assign_in_env
dans variables.c
la source de bash, par exemple.
fork
alors libc effectue l' sys_fork
appel à l'aide de l'environnement alloué par tas pour le processus enfant.
argv
sont plus courants mais les deux existent).
Vous pouvez lire l' environnement initial d'un processus à partir de /proc/<pid>/environ
.
Si un processus modifie son environnement, pour lire l'environnement, vous devez disposer de la table des symboles pour le processus et utiliser l' ptrace
appel système (par exemple, à l'aide de gdb
) pour lire l'environnement à partir de la char **__environ
variable globale . 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 pour quelques notes.
Ce qui précède suppose que le processus est conforme à POSIX, ce qui signifie qu'il gère son environnement à l'aide d'une variable globale char **__environ
spécifiée dans la spécification de référence .
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 est le cas linux//fs/exec.c:do_execve_common(...)
.) Étant donné que la taille de la mémoire tampon est calculée au maximum de la taille requise pour l'environnement initial, vous ne pouvez pas ajouter de nouvelles variables sans effacer les variables existantes ou détruire la pile. Ainsi, tout schéma raisonnable permettant des modifications dans l'environnement d'un processus utiliserait le tas, où de 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
, il est conforme à POSIX. Après __environ
avoir été déclaré dans glibc//posix/environ.c
Glibc, il est initialisé __environ
avec un pointeur sur la mémoire malloc
extraite du segment de mémoire du processus, puis copie l’environnement initial de la pile dans cette zone. Chaque fois que le processus utilise la setenv
fonction, glibc
ne a realloc
pour ajuster la taille de la surface qui __environ
pointe vers pour tenir compte de la nouvelle valeur ou variable. (Vous pouvez télécharger le code source de glibc avec git clone git://sourceware.org/git/glibc.git glibc
). Pour bien comprendre le mécanisme, vous devrez également lire le code Hurd dans hurd//init/init.c:frob_kernel_process()
(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).
Maintenant , si le nouveau processus fork
n'ed, sans suite exec
écraser la pile, l'argument et l' environnement magique de la copie se fait dans linux//kernel/fork.c:do_fork(...)
, où les copy_process
appels de routine dup_task_struct
qui attribue 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 à l' aide alloc_thread_info_node
.
Enfin, la __environ
convention POSIX est une convention d’ espace utilisateur . 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érer 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 sys_exec
. Il est probable que personne ne sera en mesure de deviner où vous mettez les changements dans votre environnement.
/proc/[pid]/
semblent avoir un encodage étrange (quelqu'un d'autre peut savoir quoi et pourquoi). Pour moi, il cat environ
suffirait d’imprimer les variables d’environnement dans un format très difficile à lire. cat environ | strings
résolu ceci pour moi.
Il est mis à jour au fur et à mesure que le processus acquiert / supprime ses variables d'environnement. Avez-vous une référence indiquant que le environ
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 au ps
format de sortie. Un traitement de texte (analyse / filtrage) est nécessaire pour afficher les variables d’environnement sous forme de liste.
Solaris (non demandé, mais pour référence je posterai ici):
/usr/ucb/ps -wwwe <pid>
ou
pargs -e <pid>
EDIT: / proc / pid / environ n'est pas mis à jour! Je me suis trompé. Le processus de vérification est ci-dessous. Cependant, les enfants dont le processus est fork 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: xargs est ici un processus enfant et hérite donc de la variable d’environnement et se reflète également dans son /proc/self/environ
fichier.
[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]$
Vérification à partir d'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 à partir d'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 qu'il lit donc son propre fichier environ.
[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$
terminal2: sur le même hôte - ne le lancez pas dans le même shell que celui où la variable ci-dessus a été définie, lancez le terminal séparément.
[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
dans la session de one bash (pid xxxx), puis cat /proc/xxxx/environ | tr \\0 \\n
dans la session de l'autre bash et je ne vois pas foo
.
gdb
au pid, mais toujours aucune référence. Le bloc de variables d'environnement en mémoire est réaffecté chaque fois qu'il y a un changement et qu'il n'est pas reflété dans le fichier d'environnement de son propre processus dans le système de fichiers proc, mais permet cependant d'être hérité par le processus enfant. Cela signifie que cela pourrait devenir plus facile de connaître les détails intrinsèques lorsque la fourchette se produit, comment le processus enfant obtient-il les variables d'environnement copiées telles quelles.
Ce qui suit n’est pas lié aux intentions réelles de l’auteur, mais si vous voulez vraiment "LIRE" le /proc/<pid>/environ
, vous pouvez essayer
strings /proc/<pid>/environ
qui est meilleur que cat
ça.
strings
. Rester simple.
xargs --null
.
tr '\0' '\n' < /proc/$$/environ | ...