¿Cuál es la diferencia entre set, export y env y cuándo debo usar cada uno?

112

De vez en cuando, elimino un script de bash y me parece que hay algunas formas de establecer una variable:

key=value
env key=value
export key=value

Cuando está dentro de un script o un comando único (por ejemplo, a menudo encadenaré una variable con un lanzador Wine para establecer el prefijo Wine correcto), estos parecen ser completamente intercambiables, pero seguramente ese no puede ser el caso.

¿Cuál es la diferencia entre estos tres métodos y puede darme un ejemplo de cuándo me gustaría usar cada uno específicamente?

Definitivamente relacionado con ¿Cuál es la diferencia entre `VAR = ...` y `export VAR = ...`? pero también quiero saber cómo envencaja esto, y algunos ejemplos que muestran los beneficios de cada uno también serían buenos :)

Oli
fuente
55
Tenga en cuenta que export key=valuees una sintaxis extendida y no debe usarse en scripts portátiles (es decir #! /bin/sh).
Simon Richter

Respuestas:

110

Consideremos un ejemplo específico. El grepcomando usa una variable de entorno llamada GREP_OPTIONSpara establecer las opciones predeterminadas.

Ahora. Dado que el archivo test.txtcontiene las siguientes líneas:

line one
line two

ejecutar el comando grep one test.txtvolverá

line one

Si ejecuta grep con la -vopción, devolverá las líneas no coincidentes, por lo que la salida será

line two

Ahora intentaremos establecer la opción con una variable ambiental.

  1. Las variables de entorno configuradas sin exportno se heredarán en el entorno de los comandos que está llamando.

    GREP_OPTIONS='-v'
    grep one test.txt

    El resultado:

    line one

    Obviamente, la opción -vno se pasó a grep.

    Desea usar este formulario cuando configura una variable solo para que la use el shell, por ejemplo for i in * ; do, si no desea exportar $i.

  2. Sin embargo, la variable se pasa al entorno de esa línea de comando en particular, por lo que puede hacer

    GREP_OPTIONS='-v' grep one test.txt

    que devolverá lo esperado

    line two

    Utiliza este formulario para cambiar temporalmente el entorno de esta instancia particular del programa lanzado.

  3. Exportar una variable hace que la variable se herede:

    export GREP_OPTIONS='-v'
    grep one test.txt

    vuelve ahora

    line two

    Esta es la forma más común de establecer variables para el uso de procesos iniciados posteriormente en un shell

  4. Todo esto se hizo en bash. exportes un bash incorporado; VAR=whateveres la sintaxis bash. env, por otro lado, es un programa en sí mismo. Cuando envse llama, suceden las siguientes cosas:

    1. El comando envse ejecuta como un nuevo proceso.
    2. env modifica el medio ambiente y
    3. llama al comando que se proporcionó como argumento. El envproceso es reemplazado por el commandproceso.

    Ejemplo:

    env GREP_OPTIONS='-v' grep one test.txt

    Este comando lanzará dos nuevos procesos: (i) env y (ii) grep (en realidad, el segundo proceso reemplazará al primero). Desde el punto de vista del grepproceso, el resultado es exactamente el mismo que ejecutar

    GREP_OPTIONS='-v' grep one test.txt

    Sin embargo, puede usar este idioma si está fuera de bash o no desea iniciar otro shell (por ejemplo, cuando está utilizando la exec()familia de funciones en lugar de la system()llamada).

Nota adicional sobre #!/usr/bin/env

Esta es también la razón por la cual #!/usr/bin/env interpreterse usa el idioma en lugar de #!/usr/bin/interpreter. envno requiere una ruta completa a un programa, porque usa la execvp()función que busca a través de la PATHvariable como lo hace un shell, y luego se reemplaza por la ejecución del comando. Por lo tanto, se puede utilizar para averiguar dónde se "sienta" un intérprete (como perl o python) en el camino.

También significa que al modificar la ruta actual puede influir en qué variante de Python se llamará. Esto hace posible lo siguiente:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

en lugar de lanzar Calibre, resultará en

I am an evil interpreter!
enero
fuente
¿Por qué funciona GREP_OPTIONS = '- v' grep one test.txt? Pensé que necesitaba un punto y coma después de '-v' (pero lo intenté y de hecho funciona.)
Joe
2
Porque con un punto y coma, se interpreta como dos comandos bash separados; el primero establece la variable (sin exportarlo), y el segundo comienza con un entorno que no tiene la variable exportada. Sin el punto y coma, sin embargo, este es un comando (grep), precedido por establecer un entorno local.
Enero
¿De dónde vienen todas las variables env? Quiero decir, cuando abres un nuevo shell siempre tienes algunas variables. Así algún programa debe haber exported aquellos, ¿verdad?
Pithikos
1
@Pithikos Las variables de entorno se configuran "obteniendo un entorno". Por defecto, bash generará un bashrc en todo el sistema (o profile.d o bash_profile). Luego obtiene su usuario ~ / .bashrc (y / o ~ / .bash_profile). Cualquiera de estos archivos puede contener comandos bash para obtener otros scripts, por lo que, en última instancia, puede tener variables de entorno procedentes de todas partes.
Eric
55
¿Qué hay de set var=blah?
CMCDragonkai