Si los procesos heredan el entorno del padre, ¿por qué necesitamos exportar?

72

Leí aquí que el propósito de exportun shell es hacer que la variable esté disponible para los subprocesos iniciados desde el shell.

Sin embargo, también he leído aquí y aquí que "los procesos heredan su entorno de sus padres (el proceso que los inició)".

Si este es el caso, ¿por qué necesitamos export? ¿Qué me estoy perdiendo?

¿Las variables de shell no son parte del entorno por defecto? ¿Cuál es la diferencia?

Amelio Vazquez-Reina
fuente

Respuestas:

75

Su suposición es que las variables de shell están en el entorno . Esto es incorrecto. El exportcomando es lo que define un nombre para estar en el entorno. Así:

a=1 b=2
export b

da como resultado que el shell actual sepa que se $aexpande a 1 y $ba 2, pero los subprocesos no sabrán nada aporque no es parte del entorno (incluso en el shell actual).

Algunas herramientas útiles:

  • set: Útil para ver los parámetros actuales del shell, exportados o no
  • set -k: Establece args asignados en el entorno. Considerarf() { set -k; env; }; f a=1
  • set -a: Le dice al shell que ponga cualquier nombre que se establezca en el entorno. Como poner exportantes de cada tarea. Útil para .envarchivos, como en set -a; . .env; set +a.
  • export: Le dice al shell que ponga un nombre en el entorno. Exportar y asignar son dos operaciones completamente diferentes.
  • env: Como comando externo, envsolo puede informarle sobre el entorno heredado , por lo tanto, es útil para la comprobación de la cordura.
  • env -i: Útil para limpiar el entorno antes de iniciar un subproceso.

Alternativas a export:

  1. name=val command # La asignación antes del comando exporta ese nombre al comando.
  2. declare/local -x name # Exporta el nombre, particularmente útil en las funciones de shell cuando desea evitar exponer el nombre al alcance externo.
  3. set -a # Exporta cada siguiente tarea.
kojiro
fuente
3
set -kes para que se pueda usar cmd ENVVAR=valueen lugar de ENVVAR=value cmd, eso no funcionará en su ejemplo a menos que set -kse haya ejecutado antes de invocar f. Además, no hay muchos shells que lo admitan hoy en día y solo por compatibilidad con el shell Bourne. En el shell Bourne (o Korn), eso no funcionaría para las funciones. Y debido a que afecta el análisis del shell, tiene que estar vigente en el momento en que el shell lee el código que lo utiliza allí.
Stéphane Chazelas
1
También es posible que desee mencionarset -a
Stéphane Chazelas
24

Hay una diferencia entre las variables de shell y las variables de entorno. Si define una variable de shell sin exportutilizarla, no se agrega al entorno de procesos y, por lo tanto, no se hereda a sus elementos secundarios.

Usando exportle dice al shell que agregue la variable del shell al entorno. Puede probar esto usando printenv(que solo imprime su entorno stdout, ya que es un proceso secundario donde ve el efecto de exportlas variables):

#!/bin/sh

MYVAR="my cool variable"

echo "Without export:"
printenv | grep MYVAR

echo "With export:"
export MYVAR
printenv | grep MYVAR
Andreas Wiese
fuente
6

Una variable, una vez exportada, es parte del entorno. PATHse exporta en el propio shell, mientras que las variables personalizadas se pueden exportar según sea necesario. Usando un código de configuración:

$ cat subshell.sh 
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='

Comparar

$ cat test.sh 
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh 
PATH=/bin
foo=bar
PATH=/bin
foo=bar

Con

$ cat test2.sh 
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh 
PATH=/bin
foo=bar
PATH=/bin

Como fooel shell test2.shno lo exporta y nunca lo exportó, no fue parte del entorno de subshell.shla última ejecución.

l0b0
fuente