linux - mp3tag - Definiendo una variable con o sin exportación
mp3 tag linux (14)
Aquí hay otro ejemplo:
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 utilizando exportar VARTEST el valor de VARTEST está disponible en sudo bash -c ''...''!
Para más ejemplos ver:
bash-hackers.org/wiki/doku.php/scripting/processtree
¿Para qué sirve la export
?
Cuál es la diferencia entre:
export name=value
y
name=value
Aunque no se menciona explícitamente en la discusión, NO es necesario usar la exportación cuando se genera una subshell desde dentro de bash ya que todas las variables se copian en el proceso secundario.
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 hijo.
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 configuradas 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. 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. Debe mencionarse que Bash (a diferencia de Python) solo admite variables de cadena.
La notación para definir las variables Bash es name=value
. Estas variables permanecen dentro de Bash y no tienen nada que ver con las variables de entorno mantenidas por el sistema operativo.
Más sobre Parámetros de Shell (incluyendo 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 puede aumentarse temporalmente prefijándolo 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 utiliza para establecer la variable de entorno en el sistema operativo. Esta variable estará disponible para todos los procesos secundarios creados por el proceso actual de Bash. - La notación de variable Bash (nombre = valor) se usa para establecer variables locales disponibles solo para el proceso actual de bash
- La notación de variable de Bash que prefija otro comando crea una variable de entorno solo para el alcance de ese comando.
De forma predeterminada, las variables creadas dentro de un script solo están disponibles para el shell actual; Los procesos secundarios (sub-shells) 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.
Debe tenerse en cuenta que puede exportar una variable y luego cambiar el valor. El valor cambiado de la variable estará disponible para los procesos secundarios. Una vez que se haya configurado la exportación para una variable, debe 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
Dos de los creadores de UNIX, Brian Kernighan y Rob Pike, explican esto en su libro "El entorno de programación UNIX". Google para el título y encontrarás 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 que se pueda acceder al valor de una variable en sub-shells, debe utilizarse el comando de exportación del shell. (Podría pensar por qué no hay manera de exportar el valor de una variable desde un sub-shell a su padre).
La respuesta aceptada implica esto, pero me gustaría hacer explícita la conexión a los shell shell:
Como ya se mencionó, la export
hará que una variable esté disponible tanto para el shell como para los hijos. Si no se usa la export
, la variable solo estará disponible en el shell, y solo los buildins del shell 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
Otros han respondido que la exportación hace que la variable esté disponible para subshells, y eso es correcto, pero simplemente un efecto secundario. Cuando exporta una variable, coloca esa variable en el entorno del shell actual (es decir, el shell llama putenv (3) o setenv (3)). El entorno de un proceso se hereda en exec, lo que hace que la variable sea visible en subshells.
Editar (con perspectiva de 5 años): esta es una respuesta tonta. El propósito de ''exportar'' es hacer que las variables "estén en el entorno de los comandos ejecutados posteriormente", ya sea que estos comandos sean subshells o subprocesos. Una implementación ingenua sería simplemente poner la variable en el entorno del shell, pero esto haría imposible implementar export -p
.
Para ilustrar lo que dicen las otras respuestas:
$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar
bash-3.2$
Se ha dicho que no es necesario exportar en bash cuando se generan subshells, mientras que otros dicen exactamente lo contrario. Es importante tener en cuenta la diferencia entre las subshells (las que se crean por ()
, ``
, $()
o los loops) y los subprocesos (procesos que se invocan por su nombre, por ejemplo, una bash
literal en su script). Las subshells tendrán acceso a todas las variables del padre, independientemente de su estado exportado. Los subprocesos, por otra parte, solo verán las variables exportadas. Lo que es común en estas dos construcciones es que ninguna de las dos puede volver a pasar 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:
Hay una fuente de confusión más: algunos piensan que los subprocesos "bifurcados" son los que no ven las 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 hay que buscar, mientras que en realidad es el exec (). Puede ejecutar los comandos sin fork () primero con el comando exec
, y los procesos iniciados por este método tampoco tendrán acceso a las 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 la línea parent:
esta vez, porque hemos reemplazado el shell padre con el comando exec
, por lo que no queda nada para ejecutar ese comando.
Solo para mostrar la diferencia entre una variable exportada que se encuentra en el entorno (env) y una variable no exportada que no está en el entorno:
Si hago esto:
$ MYNAME=Fred
$ export OURNAME=Jim
entonces solo aparece $ OURNAME en el env. La variable $ MYNAME no está en el env.
$ env | grep NAME
OURNAME=Jim
pero la variable $ MYNAME existe en el shell
$ echo $MYNAME
Fred
export NAME=value
para configuraciones y variables que tienen significado para un subproceso.
NAME=value
para variables temporales o de bucle privadas al proceso de shell actual.
En más detalle, la export
marca el nombre de la variable en el entorno que se copia en un subproceso y sus subprocesos en la creación. No se vuelve a copiar ningún nombre o valor desde el subproceso.
Un error común es colocar un espacio alrededor del signo igual:
$ export FOO = "bar" bash: export: `='': not a valid identifier
El subproceso solo ve la variable exportada (
B
):$ 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 exportar 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 pasan a formar parte del entorno (ambiente
man environ
):$ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE/|BOB" BOB=Bob
Entonces, ¡ahora debería ser tan claro como el sol del verano! Gracias a Brain Agnew, alexp y William Prusell.
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 ámbito 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 la exportación de una variable no hace que esté disponible para los procesos principales. Es decir, especificar y exportar una variable en un proceso generado no lo hace disponible en el proceso que lo lanzó.
export
hará que la variable esté disponible para todos los shells bifurcados del shell actual.