Estoy interesado en establecer variables ambientales de una instancia de shell de otra. Entonces decidí investigar un poco. Después de leer una serie de preguntas sobre esto , decidí probarlo.
Engendré dos proyectiles A y B (PID 420), ambos corriendo zsh. Desde shell AI ejecutó lo siguiente.
sudo gdb -p 420
(gdb) call setenv("FOO", "bar", 1)
(gdb) detach
Desde el shell B cuando ejecuto envpuedo ver que la variable FOO está configurada con un valor de barra. Esto me hace pensar que FOO se ha inicializado con éxito en el entorno de shell B. Sin embargo, si trato de imprimir FOO obtengo una línea vacía que implica que no está configurada. Para mí, parece que hay una contradicción aquí.
Esto fue probado tanto en mi propio sistema Arch GNU / Linux como en una máquina virtual Ubuntu. También probé esto en bashdonde la variable ni siquiera apareció en env. Esto, aunque es decepcionante para mí, tiene sentido si el shell almacena en caché una copia de su entorno en el momento de la generación y solo usa eso (lo que se sugirió en una de las preguntas vinculadas). Esto todavía no responde por qué zshpuede ver la variable.
¿Por qué la salida de echo $FOOvacío?
EDITAR
Después de la entrada en los comentarios, decidí hacer un poco más de pruebas. Los resultados se pueden ver en las tablas a continuación. En la primera columna está el shell en el que FOOse inyectó la variable. La primera fila contiene el comando cuyo resultado se puede ver debajo de él. La variable FOOse inyectó usando: sudo gdb -p 420 -batch -ex 'call setenv("FOO", "bar", 1)'. Los comandos específicos de zsh: zsh -c '...'también se probaron con bash. Los resultados fueron idénticos, su producción se omitió por brevedad.
Arch GNU / Linux, zsh 5.3.1, bash 4.4.12 (1)
| | env | grep FOO | echo $FOO | zsh -c 'env | grep FOO' | zsh -c 'echo $FOO' | After export FOO |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh | FOO=bar | | FOO=bar | bar | No Change |
| bash | | bar | | | Value of FOO visible in all tests |
Ubuntu 16.04.2 LTS, zsh 5.1.1, bash 4.3.48 (1)
| | env | grep FOO | echo $FOO | zsh -c 'env | grep FOO' | zsh -c 'echo $FOO' | After export FOO |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh | FOO=bar | | FOO=bar | bar | No Change |
| bash | | bar | | | Value of FOO visible in all tests |
Lo anterior parece implicar que los resultados son independientes de la distribución. Esto no me dice mucho más zshy bashmaneja la configuración de variables de manera diferente. Además, export FOOtiene un comportamiento muy diferente en este contexto dependiendo del shell. Esperemos que estas pruebas puedan aclararle algo a alguien más.

zsh -c 'echo $FOO'(usa comillas simples) en su lugar? ¿Puedes verlo entonces?env) ven el entorno modificado.zshen GDB no lo hace visible como una variable de shell, pero hace que se pase a procesos secundarios (como ha observado), mientras que establecer uno parabashsí lo hace visible como una variable de shell, ¡pero no hace que se pase a procesos secundarios! Parece que zsh y bash usan diferentes estrategias para administrar variables, con zsh que rastrea variables que no son de entorno y bash almacena todo en su entorno que desinfecta cuando se inicia un hijo (sin subshell).export FOOenbash?Respuestas:
La mayoría de los shells no usan la API
getenv()/setenv()/putenv().Al iniciarse, crean variables de shell para cada variable de entorno. Esos serán almacenados en estructuras internas que necesitan transportar otra información, como si la variable se exporta, solo lectura ... No pueden usar las bibliotecas
environpara eso.Del mismo modo, y por esa razón, no van a utilizar
execlp(),execvp()para ejecutar comandos, pero llamar a laexecve()llamada al sistema directamente, el cálculo de laenvp[]matriz en base a la lista de sus variables exportadas.Entonces, en su
gdb, necesitaría agregar una entrada a esa tabla interna de variables de shells, o posiblemente llamar a la función correcta que lo haría interpretar unexport VAR=valuecódigo para actualizar esa tabla por sí mismo.En cuanto a por qué se ve una diferencia entre
bashyzshcuando se llamasetenv()engdb, Sospecho que es porque usted está llamandosetenv()antes de que los inicializa shell, por ejemplo al entrarmain().Notarás
bash'smain()isint main(int argc, char* argv[], char* envp[])(ybashasigna variables de esos entornosenvp[]) mientras quezsh' s esint main(int argc, char* argv[])yzshobtiene las variables en suenvironlugar.setenv()modificaenvironpero no puede modificarenvp[]en el lugar (solo lectura en varios sistemas, así como las cadenas a las que apuntan estos punteros).En cualquier caso, después de que el shell haya leído
environen el inicio, el usosetenv()sería ineficaz ya que el shell ya no usaenviron(ogetenv()) después.fuente