[linux] Definir una variable con o sin exportación


6 Answers

Para ilustrar lo que dicen las otras respuestas:

al$ foo="Hello, World"
al$ echo $foo
Hello, World
al$ bar="Goodbye"
al$ export foo
al$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar

bash-3.2$ 
Question

¿Para qué se export ?

Cuál es la diferencia entre:

export name=value

y

name=value



Como ya sabrá, 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 de 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 principales. 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 establecer sus variables de entorno a petición del usuario. Esto es para lo que existe la export .

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 este Bash crearía.

Más sobre el medio ambiente en Bash

Otro tipo de variable en Bash es la variable interna. Como Bash no es solo un intérprete interactivo, de hecho es un intérprete de guiones, ya que 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 las 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, según el manual de referencia de Bash:

El entorno para cualquier comando o función simple se puede aumentar temporalmente prefijando 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 notación de la variable Bash (nombre = valor) se utiliza para establecer variables locales disponibles solo para el proceso actual de bash
  • La notación de variable Bash prefijando otro comando crea una variable de entorno solo para el alcance de ese comando.



Por defecto, las variables creadas dentro de un script solo están disponibles para el shell actual; los procesos hijos (subconjuntos) no tendrán acceso a los valores que se han establecido o modificado. Permitir que los procesos secundarios vean los valores requiere el uso del comando de exportación.




export hará que la variable esté disponible para todas las shells bifurcadas desde el shell actual.




Dos de los creadores de UNIX, Brian Kernighan y Rob Pike, explican esto en su libro "El entorno de programación UNIX". Busque el título de 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 comando de export al final de esa sección:

Cuando desee hacer accesible el valor de una variable en subconjuntos, se debe usar el comando de exportación del intérprete de comandos. (Puede pensar por qué no hay forma de exportar el valor de una variable desde un subconjunto a su elemento principal).




Se ha dicho que no es necesario exportar en bash cuando se generan subcapas, mientras que otros dicen exactamente lo contrario. Es importante notar la diferencia entre subcapas (aquellas que son creadas por () , `` , $() o bucles) y subprocesos (procesos que son invocados por nombre, por ejemplo un bash literal que aparece en su script). Las subcapas tendrán acceso a todas las variables del padre, independientemente de su estado exportado. Los subprocesos, por otro lado, solo verán las variables exportadas. Lo que es común en estos dos constructos es que ninguno de los dos puede pasar variables al shell primario.

$ 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:

Existe una fuente más de confusión: algunos piensan que los subprocesos "bifurcados" son los que no ven las variables no exportadas. Usualmente fork () s son seguidos inmediatamente por exec () s, y es por eso que parece que el fork () es lo que hay que buscar, mientras que de hecho es el exec (). Puede ejecutar comandos sin fork () primero con el comando exec , y los procesos iniciados con 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 no vemos el parent: línea esta vez, porque hemos reemplazado el shell padre con el comando exec , por lo que no queda nada para ejecutar ese comando.




La respuesta aceptada implica esto, pero me gustaría hacer explícita la conexión a shell builtins:

Como ya se mencionó, export hará que una variable esté disponible tanto para el shell como para los hijos. Si no se utiliza la export , la variable solo estará disponible en el shell, y solo los shell builtins pueden acceder a ella.

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



Related