Respuestas:
export
hace que la variable esté disponible para subprocesos.
Es decir,
export name=value
significa que el nombre de la variable está disponible para cualquier proceso que ejecute desde ese proceso de shell. Si desea que un proceso haga uso de esta variable, use export
y ejecute el proceso desde ese shell.
name=value
significa que el alcance variable está restringido al shell y no está disponible para ningún otro proceso. Usaría esto para (digamos) variables de bucle, variables temporales, etc.
Es importante tener en cuenta que exportar una variable no la pone a disposición de los procesos principales. Es decir, especificar y exportar una variable en un proceso generado no la hace disponible en el proceso que la lanzó.
name=value command
hace que la variable esté disponible en el subproceso command
.
Otros han respondido que exportar hace que la variable esté disponible para subcapas, y eso es correcto pero simplemente un efecto secundario. Cuando exporta una variable, la coloca en el entorno del shell actual (es decir, el shell llama putenv(3)
o setenv(3)
).
El entorno de un proceso se hereda a través de exec, lo que hace que la variable sea visible en subcapas.
Editar (con perspectiva de 5 años): esta es una respuesta tonta. El propósito de 'exportar' es hacer que las variables "se encuentren en el entorno de los comandos ejecutados posteriormente", ya sean comandos o subprocesos. Una implementación ingenua sería simplemente poner la variable en el entorno del shell, pero esto haría que sea imposible de implementar export -p
.
bash
, export de hecho agrega la variable al entorno del shell actual, pero este no es el caso con dash
. Me parece que agregar la variable al entorno del shell actual es la forma más sencilla de implementar la semántica de export
, pero ese comportamiento no es obligatorio.
dash
tiene que ver esto. El póster original preguntaba específicamente sobre bash
.
bash
pero se aplica igualmente a cualquier variante de caparazón de bourne. Ser demasiado específico y proporcionar respuestas que se aplican solo a bash
es un gran mal.
bash
es el jQuery del shell.
export makes the variable available to subshells, and that is correct
Este es un uso muy confuso de la terminología. Las subcapas no necesitan export
heredar variables. Los subprocesos sí.
Se ha dicho que no es necesario exportar en bash cuando se generan subcapas, mientras que otros dicen exactamente lo contrario. Es importante tener en cuenta la diferencia entre subniveles (aquellos que son creados por ()
, ``
, $()
o bucles) y subprocesos (procesos que se invocan por su nombre, por ejemplo, un literal bash
que aparece en el script).
Lo que es común en estas dos construcciones es que ninguna de las dos puede devolver variables al shell principal.
$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:
Hay otra fuente de confusión: algunos piensan que los subprocesos 'bifurcados' son los que no ven variables no exportadas. Por lo general, los fork () s son seguidos inmediatamente por exec () s, y es por eso que parece que el fork () es lo que debe buscarse, mientras que de hecho es el exec (). Puede ejecutar comandos sin fork () primero con el exec
comando, y los procesos iniciados por este método tampoco tendrán acceso a variables no exportadas:
$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export
Tenga en cuenta que parent:
esta vez no vemos la línea, porque hemos reemplazado el shell principal con el exec
comando, por lo que no queda nada para ejecutar ese comando.
&
) también crea una subshell.
var=asdf bash -c 'echo $var'
o var=asdf exec bash -c 'echo $var'
? La salida es asdf
. La ;
diferencia se coloca después de la definición de la variable. ¿Cuál sería la explicación? Parece que el var
(sin ;
) respecto al subproceso generado de alguna manera, debido a que el shell de origen no tiene nada que ver con eso. echo $var
no imprime nada si se ejecuta en la segunda línea. Pero uno alineado var=asdf bash -c 'echo $var'; echo $var
da asdf\nasdf
.
export NAME=value
para configuraciones y variables que tienen significado para un subproceso.
NAME=value
para variables temporales o de bucle privadas para el proceso de shell actual.
Con más detalle, export
marca el nombre de la variable en el entorno que se copia en un subproceso y sus subprocesos en el momento de la creación. Ningún nombre o valor se copia del subproceso.
Un error común es colocar un espacio alrededor del signo igual:
$ export FOO = "bar"
bash: export: `=': not a valid identifier
El B
subproceso solo ve la variable exportada ( ):
$ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
A is . B is Bob
Los cambios en el subproceso no cambian el shell principal:
$ export B="Bob"; echo 'B="Banana"' | bash; echo $B
Bob
Las variables marcadas para exportación tienen valores copiados cuando se crea el subproceso:
$ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
[1] 3306
$ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash
Subprocess 1 has B=Bob
Subprocess 2 has B=Banana
[1]+ Done echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
Solo las variables exportadas se vuelven parte del entorno ( man environ
):
$ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
BOB=Bob
Entonces, ¡ahora debería estar tan claro como el sol del verano! Gracias a Brain Agnew, alexp y William Prusell.
Cabe señalar que puede exportar una variable y luego cambiar el valor. El valor modificado de la variable estará disponible para los procesos secundarios. Una vez que se ha establecido la exportación para una variable, debe hacer export -n <var>
para eliminar la propiedad.
$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
Como ya sabrás, UNIX permite que los procesos tengan un conjunto de variables de entorno, que son pares clave / valor, tanto la clave como el valor son cadenas. El sistema operativo es responsable de mantener estos pares para cada proceso por separado.
El programa puede acceder a sus variables de entorno a través de esta API UNIX:
char *getenv(const char *name);
int setenv(const char *name, const char *value, int override);
int unsetenv(const char *name);
Los procesos también heredan variables de entorno de los procesos primarios. El sistema operativo es responsable de crear una copia de todos los "envars" en el momento en que se crea el proceso secundario.
Bash , entre otros shells, es capaz de configurar sus variables de entorno a petición del usuario. Para eso export
existe.
export
es un comando Bash para establecer la variable de entorno para Bash. Todas las variables establecidas con este comando serían heredadas por todos los procesos que crearía este Bash.
Más sobre el medio ambiente en Bash
Otro tipo de variable en Bash es la variable interna. Dado que Bash no es solo un shell interactivo, de hecho es un intérprete de script, como cualquier otro intérprete (por ejemplo, Python) es capaz de mantener su propio conjunto de variables. Cabe mencionar que Bash (a diferencia de Python) solo admite variables de cadena.
La notación para definir variables de Bash es name=value
. Estas variables permanecen dentro de Bash y no tienen nada que ver con las variables de entorno que mantiene el sistema operativo.
Más sobre los parámetros de Shell (incluidas las variables)
También vale la pena señalar que, de acuerdo con el manual de referencia de Bash:
El entorno para cualquier comando o función simple puede aumentarse temporalmente con el prefijo con asignaciones de parámetros, como se describe en Parámetros de Shell . Estas declaraciones de asignación afectan solo al entorno visto por ese comando.
Para resumir las cosas:
export
se usa para establecer la variable de entorno en el sistema operativo. Esta variable estará disponible para todos los procesos secundarios creados por el proceso Bash actual para siempre.La respuesta aceptada implica esto, pero me gustaría hacer explícita la conexión a los componentes integrados de shell:
Como ya se mencionó, export
hará que una variable esté disponible tanto para el shell como para los hijos. Si export
se no se utiliza, la variable sólo estará disponible en la cáscara, y sólo la cáscara órdenes internas se puede acceder a él.
Es decir,
tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin
Aquí hay otro ejemplo más:
VARTEST="value of VARTEST"
#export VARTEST="value of VARTEST"
sudo env | grep -i vartest
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'
¡Solo usando export VARTEST el valor de VARTEST está disponible en sudo bash -c '...'!
Para más ejemplos ver:
bash-hackers.org/wiki/doku.php/scripting/processtree
Dos de los creadores de UNIX, Brian Kernighan y Rob Pike, explican esto en su libro "El entorno de programación de UNIX". Busque el título en Google y encontrará fácilmente una versión en pdf.
Abordan las variables de shell en la sección 3.6 y se centran en el uso del export
comando al final de esa sección:
Cuando desee que el valor de una variable sea accesible en subcapas, se debe usar el comando de exportación del caparazón. (Puede pensar en por qué no hay forma de exportar el valor de una variable desde un sub-shell a su padre).
Solo para mostrar la diferencia entre una variable exportada que se encuentra en el entorno (env) y una variable no exportada que no se encuentra en el entorno:
Si hago esto:
$ MYNAME=Fred
$ export OURNAME=Jim
entonces solo $ OURNAME aparece en la env. La variable $ MYNAME no está en el entorno.
$ env | grep NAME
OURNAME=Jim
pero la variable $ MYNAME existe en el shell
$ echo $MYNAME
Fred
Por defecto, las variables creadas dentro de un script solo están disponibles para el shell actual; Los procesos secundarios (subcapas) no tendrán acceso a los valores que se hayan establecido o modificado. Permitir que los procesos secundarios vean los valores requiere el uso del comando de exportación.
Aunque no se menciona explícitamente en la discusión, NO es necesario usar exportar cuando se genera una subshell desde adentro de bash ya que todas las variables se copian en el proceso secundario.
export name=value
no es portátil. Dependiendo de lo que quieras exactamente, pruebaname=value; export name
con una solución portátil.