GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo leer las variables de entorno de un proceso

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:

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.

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

terminal2: en el mismo host:no lo inicie en el mismo shell donde se configuró la variable anterior, inicie el terminal por separado.

[[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. Cómo establecer, enumerar y eliminar variables de entorno en Linux

  2. ¿Cómo puedo hacer que R lea mis variables ambientales?

  3. Cómo configurar las variables de entorno de Linux con Ansible

  4. ¿Cómo imprimir variables de entorno aparentemente ocultas?

  5. ¿Las variables de entorno son visibles para usuarios sin privilegios en Linux?

Cómo establecer la variable de entorno en Windows

Cómo establecer variables de entorno en MacOS

Cómo establecer y enumerar variables de entorno en Linux

Cómo establecer y enumerar variables ambientales en Linux

Cómo configurar y desactivar variables de entorno en Linux

Variables de entorno de Linux