Puedes leer la inicial entorno de un proceso de /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 el ptrace
llamada al sistema (por ejemplo, usando gdb
) para leer el entorno desde el char **__environ
global variable. No hay otra forma de obtener el valor de cualquier variable de un proceso de Linux en ejecución.
Esa es la respuesta. Ahora algunas notas.
Lo anterior asume que el proceso es compatible con POSIX, lo que significa que el proceso administra su entorno utilizando una variable global char **__environ
como se especifica en la especificación de referencia.
El entorno inicial de 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 del búfer se calcula para que no supere el tamaño requerido para el entorno inicial, no puede agregar nuevas variables sin borrar las variables existentes o destrozar la pila. Entonces, 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 GNU libc
(glibc
) hace por ti.
Si el proceso usa glibc
, entonces es compatible con POSIX, con __environ
siendo declarado en glibc//posix/environ.c
Glibc inicializa __environ
con un puntero a la memoria que malloc
s 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 el setenv
función, glibc
hace un realloc
para ajustar el tamaño del área que __environ
apunta a para acomodar el nuevo valor o variable. (Puede descargar el código fuente de glibc con git clone git://sourceware.org/git/glibc.git glibc
). Para comprender realmente el mecanismo, también deberá leer el código Hurd en hurd//init/init.c:frob_kernel_process()
(git clone git://git.sv.gnu.org/hurd/hurd.git hurd).
Ahora, si el nuevo proceso es solo fork
ed, sin un subsiguiente exec
sobrescribiendo la pila, luego el argumento y la magia de copia del entorno se realiza en linux//kernel/fork.c:do_fork(...)
, donde el copy_process
llamadas de rutina dup_task_struct
que asigna la pila del nuevo proceso llamando a alloc_thread_info_node
, que llama a setup_thread_stack
(linux//include/linux/sched.h
) para el nuevo proceso usando alloc_thread_info_node
.
Finalmente, el POSIX __environ
la convención es un espacio de usuario convención. No tiene conexión con nada en el kernel de Linux. Puede escribir un programa de espacio de usuario sin usar glibc
y sin el __environ
global y luego administre 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 contenedores para sys_exec
y es probable que nadie pueda adivinar dónde coloca los cambios en su entorno.
/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
y ps
, e incluso no todas las variantes de Unix tienen este tipo de característica, por lo que las aplicaciones no dependen de ella.
En lo que respecta al kernel, el entorno solo aparece como argumento del execve
llamada al sistema que inicia el programa. Linux expone un área en la memoria a través de /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.
Se actualiza a medida que el proceso adquiere/elimina sus variables de entorno. ¿Tiene una referencia que indique el environ
¿El archivo no está actualizado para el proceso en su directorio de procesos en /proc filesystem?
xargs --null --max-args=1 echo < /proc/self/environ
o
xargs --null --max-args=1 echo < /proc/<pid>/environ
o
ps e -p <pid>
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 solicitado, pero como referencia lo publicaré aquí):
/usr/ucb/ps -wwwe <pid>
o
pargs -e <pid>
EDITAR: ¡/proc/pid/environ no está actualizado! Estoy corregido. El proceso de verificación se encuentra a continuación. Sin embargo, los elementos secundarios de los que se bifurca el proceso heredan la variable de entorno del proceso y es visible en su respectivo archivo /proc/self/environ. (Usar cadenas)
Dentro del shell:aquí xargs es un proceso secundario y, por lo tanto, hereda la variable de entorno y también se refleja en su /proc/self/environ
archivo.
[[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]$
Verificándolo desde otra sesión, donde la terminal/sesión no es el proceso secundario del shell donde se establece la variable de entorno.
Verificación desde otra terminal/sesión en el mismo host:
[[email protected] t]$ echo $$
2610
[[email protected] t]$ export SPIDEY=NIKHIL
[[email protected] t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[[email protected] t]$
[[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] ~]$