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

92

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

key=value
env key=value
export key=value

Cuando estás dentro de un script o un comando único (por ejemplo, a menudo encadenaré una variable con un Wine launcher para configurar 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 quisiera usar cada uno específicamente?

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

    
pregunta Oli 24.10.2012 - 11:34

1 respuesta

92

Consideremos un ejemplo específico. El comando grep usa una variable de entorno llamada GREP_OPTIONS para establecer las opciones predeterminadas.

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

line one
line two

ejecutar el comando grep one test.txt devolverá

line one

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

line two

Ahora intentaremos establecer la opción con una variable de entorno.

  1. Las variables de entorno establecidas sin export no se heredarán en el entorno de los comandos a los que llama.

    GREP_OPTIONS='-v'
    grep one test.txt
    

    El resultado:

    line one
    

    Obviamente, la opción -v no pasó a grep .

    Desea utilizar este formulario cuando está configurando una variable solo para el shell, por ejemplo, en for i in * ; do no desea exportar $i .

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

    GREP_OPTIONS='-v' grep one test.txt
    

    que devolverá el esperado

    line two
    

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

  3. La exportación de 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. export es un bash incorporado; VAR=whatever es la sintaxis de bash. env , por otro lado, es un programa en sí mismo. Cuando se llama env , sucede lo siguiente:

    1. El comando env se ejecuta como un nuevo proceso
    2. env modifica el entorno y
    3. llama al comando que se proporcionó como argumento. El proceso env se reemplaza por el proceso command .

    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 proceso grep , el resultado exactamente es lo mismo que ejecutar

    GREP_OPTIONS='-v' grep one test.txt
    

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

Nota adicional sobre #!/usr/bin/env

Esta es también la razón por la cual se usa la expresión #!/usr/bin/env interpreter en lugar de #!/usr/bin/interpreter . env no requiere una ruta completa a un programa, porque usa la función execvp() que busca a través de la variable PATH como lo hace un shell, y luego reemplaza por el comando run . Por lo tanto, se puede usar para averiguar dónde se encuentra "sentado" un intérprete (como Perl o Python) en la ruta.

También significa que al modificar la ruta actual puede influir sobre la variante de python a la que 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 ejecutar Calibre, dará como resultado

I am an evil interpreter!
    
respondido por el January 24.10.2012 - 12:21

Lea otras preguntas en las etiquetas