Linux /proc/<pid>/environ
no se actualiza (según tengo entendido, el archivo contiene el entorno inicial del proceso).
¿Cómo puedo leer el entorno actual de un proceso ?
fuente
Linux /proc/<pid>/environ
no se actualiza (según tengo entendido, el archivo contiene el entorno inicial del proceso).
¿Cómo puedo leer el entorno actual de un proceso ?
/proc/$pid/environ
se actualiza si el proceso cambia su propio entorno. Pero muchos programas no se molestan en cambiar su propio entorno, porque es un poco inútil: el entorno de un programa no es visible a través de los canales normales, solo a través de /proc
e ps
, e incluso no todas las variantes de Unix tienen este tipo de característica, por lo que las aplicaciones no dependen en eso.
En lo que respecta al núcleo, el entorno solo aparece como el argumento de la execve
llamada al sistema que inicia el programa. Linux expone un área en la memoria /proc
, y algunos programas actualizan esta área mientras que otros no. En particular, no creo que ningún shell actualice esta área. Como el área tiene un tamaño fijo, sería imposible agregar nuevas variables o cambiar la longitud de un valor.
PATH=foo
en un shell no significa que el shell se va a modificar*envp
. En algunos shells, eso solo actualizó una estructura de datos interna, y es el código de ejecución del programa externo el que se actualiza*envp
. Miraassign_in_env
envariables.c
la fuente de fiesta, por ejemplo.fork
libc realiza lasys_fork
llamada utilizando el entorno de montón asignado para el proceso secundario.argv
son más comunes pero ambos existen).Puede leer el entorno inicial de un proceso desde
/proc/<pid>/environ
.Si un proceso cambia su entorno, entonces para leer el entorno debe tener la tabla de símbolos para el proceso y usar la
ptrace
llamada al sistema (por ejemplo, usandogdb
) para leer el entorno de lachar **__environ
variable global . No hay otra forma de obtener el valor de ninguna variable de un proceso Linux en ejecución.Esa es la respuesta. Ahora para algunas notas.
Lo anterior supone que el proceso es compatible con POSIX, lo que significa que el proceso gestiona su entorno utilizando una variable global
char **__environ
como se especifica en la Especificación de referencia .El entorno inicial para un proceso se pasa al proceso en un búfer de longitud fija en la pila del proceso. (El mecanismo habitual que hace esto es
linux//fs/exec.c:do_execve_common(...)
.) Dado que el tamaño de la memoria intermedia se calcula a no ser más que el tamaño requerido para el medio ambiente inicial, no se puede agregar nuevas variables sin borrar las variables existentes o rompiendo la pila. Por lo tanto, cualquier esquema razonable para permitir cambios en el entorno de un proceso usaría el montón, donde se puede asignar y liberar memoria en tamaños arbitrarios, que es exactamente lo que GNUlibc
(glibc
) hace por usted.Si el proceso usa
glibc
, entonces es compatible con POSIX, y__environ
al declararse englibc//posix/environ.c
Glibc se inicializa__environ
con un puntero a la memoria quemalloc
proviene del montón del proceso, luego copia el entorno inicial de la pila en esta área del montón. Cada vez que el proceso usa lasetenv
función,glibc
hace unarealloc
para ajustar el tamaño del área que__environ
apunta para acomodar el nuevo valor o variable. (Puede descargar el código fuente de glibc congit clone git://sourceware.org/git/glibc.git glibc
). Para comprender realmente el mecanismo, también deberá leer el código Hurd enhurd//init/init.c:frob_kernel_process()
(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).Ahora, si el nuevo proceso solo se
fork
edita, sin una posteriorexec
sobrescritura de la pila, entonces el argumento y la magia de copia del entorno se realiza enlinux//kernel/fork.c:do_fork(...)
, donde lacopy_process
rutina llamadup_task_struct
que asigna la pila del nuevo proceso llamandoalloc_thread_info_node
, que llamasetup_thread_stack
(linux//include/linux/sched.h
) para el nuevo proceso usandoalloc_thread_info_node
.Finalmente, la
__environ
convención POSIX es una convención de espacio de usuario . No tiene conexión con nada en el kernel de Linux. Puede escribir un programa de espacio de usuario sin usarglibc
y sin el__environ
global y luego administrar las variables de entorno como desee. Nadie lo arrestará por hacer esto, pero tendrá que escribir sus propias funciones de administración del entorno (setenv
/getenv
) y sus propios contenedoressys_exec
y es probable que nadie pueda adivinar dónde coloca los cambios en su entorno.fuente
/proc/[pid]/
parecen tener una codificación extraña (alguien más puede saber qué y por qué). Para mí, simplementecat environ
imprimiría las variables de entorno en un formato realmente difícil de leer.cat environ | strings
Resuelto esto por mí.Se actualiza a medida que el proceso adquiere / elimina sus variables de entorno. ¿Tiene una referencia que indique que el
environ
archivo no está actualizado para el proceso en su directorio de proceso en / proc filesystem?o
o
Lo anterior imprimirá las variables de entorno del proceso en el
ps
formato de salida, se requiere procesamiento de texto (análisis / filtrado) para ver las variables de entorno como una lista.Solaris (no preguntado, pero para referencia lo publicaré aquí):
o
EDITAR: / proc / pid / environment no se actualiza! Estoy corregido. El proceso de verificación está abajo. Sin embargo, los hijos de los que se bifurca el proceso heredan la variable de entorno del proceso y es visible en su respectivo / proc / self / environment. (Use cadenas)
Con en el shell: aquí xargs es un proceso hijo y, por lo tanto, hereda la variable de entorno y también se refleja en su
/proc/self/environ
archivo.Verificándolo desde otra sesión, donde el terminal / sesión no es el proceso hijo del shell donde se establece la variable de entorno.
Verificación desde otra terminal / sesión en el mismo host:
terminal1:: Tenga en cuenta que printenv está bifurcado y es un proceso secundario de bash y, por lo tanto, lee su propio archivo de entorno.
terminal2: en el mismo host: no lo inicie con el mismo shell donde se configuró la variable anterior, inicie el terminal por separado.
fuente
export foo=bar
en la sesión de un bash (pid xxxx), luego lo hagocat /proc/xxxx/environ | tr \\0 \\n
en la sesión de otro bash y no veofoo
.gdb
al pid, pero aún no hay referencia allí. El bloque de variables de entorno en la memoria se reasigna cada vez que hay un cambio y no se refleja en el archivo de entorno de su propio proceso en el sistema de archivos proc, pero permite que el proceso secundario lo herede. Eso significa que esto podría ser más fácil de conocer detalles intrínsecos cuando ocurre la bifurcación, cómo el proceso secundario obtiene las variables de entorno copiadas tal como están.Bueno, lo siguiente no está relacionado con las intenciones reales del autor, pero si realmente quieres "LEER" el
/proc/<pid>/environ
, puedes intentarque es mejor que
cat
esofuente
strings
. Mantenlo simple.xargs --null
.tr '\0' '\n' < /proc/$$/environ | ...