Una especie de pregunta secundaria, pero ¿cómo se llama la característica en sí cuando configura una variable de entorno para un solo subcomando como ese? Siempre me ha costado encontrar información sobre esto porque no sé cómo se llama.
John Cromartie
1
@ JohnCromartie, deberías hacer eso como una pregunta.
@ JohnCromartie Es un componente opcional de cada comando de shell, por lo que se encuentra en la sección "Comandos simples" de la mayoría de los manuales de shell. Para POSIX, eso estaría aquí . Glenn ya te ha vinculado la sección análoga del manual de bash.
jw013
Establecer una variable que no existe a través de una asignación crea una variable de shell. Configurarlo a través de ENV o exportar la variable empuja la variable al entorno de ejecución del shell. Cambiar el valor de una variable existente actualizará el valor del entorno de ejecución si existe, de lo contrario, cámbielo en las variables internas del shell.
Johan
Respuestas:
26
Son funcionalmente equivalentes.
La principal diferencia es que env FOO=bar bazimplica invocar un proceso intermedio entre el shell y baz, donde al igual que con FOO=bar bazel shell, invoca directamente baz.
Por lo tanto, en ese sentido, FOO=bar bazse prefiere.
Las únicas situaciones en las que me encuentro usando env FOO=bares donde tengo que pasar un comando a otro comando.
Como ejemplo específico, digamos que tengo un script de contenedor que realiza algunas modificaciones del entorno y luego invoca execel comando que se le pasó, como:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Si lo ejecutas como myscript FOO=bar baz , execarrojará un error como exec FOO=bar bazno válido.
En cambio, lo llama como myscript env FOO=bar bazque se ejecuta como exec env FOO=bar baz, y es perfectamente válido.
Sin FOO=bar exec bazembargo, puede hacerlo , por lo que no necesita enven su último punto.
Stéphane Chazelas
Cuando execalgo, ¿utiliza su entorno actual?
Glenn Jackman
1
Lo mismo ocurre con @StephaneChazelas, y también puede sudo FOO=bar bazpasar variables de entorno sin necesidad de hacerlo env.
Mike Miller
1
@StephaneChazelas que solo funciona si quiero incluir FOO=barel script. Si FOOno es siempre bar, no quiero a codificar ella, y en su lugar lo paso en.
Patrick
@glennjackman sí, siempre y cuando las variables se exporten o se pasen antes del exec, como FOO=bar exec baz.
Patrick
14
En este ejemplo en particular, no existe una diferencia efectiva, suponiendo que su shell es un shell compatible con POSIX, y suponiendo que bazes un ejecutable y no un shell incorporado.
Si su shell no es compatible con POSIX, por ejemplo , csho tcshla sintaxis
FOO=bar baz
no funciona y no hay una sintaxis de shell equivalente. Para esas conchas, elenv comando es la única forma de anular o inyectar variables de entorno para un solo comando.
Si bazes un shell integrado, digamos, fcpor ejemplo, envno dará los mismos resultados, porque envestá ejecutando un nuevo proceso en lugar de ser ejecutado directamente por el shell del comando. Además, no hay un fcejecutable, solo puede ejecutarse como un shell integrado debido a la forma en que interactúa con el entorno del shell, y también lo envhará nunca funcionará con un tipo incorporado fc.
Además, envofrece la -iopción, que le permite iniciar un comando en un entorno vacío con solo un conjunto específico de variables de entorno. Por envlo tanto, puede ser muy útil para iniciar procesos en entornos desinfectados, por ejemplo
Cuando solía usar tcsh, escribía (setenv FOO bar; baz)para obtener la función equivalente.
Barmar
6
Además de lo que ya se ha dicho
VAR=value cmd args > redirs
Al ser una función de shell (Bourne / POSIX), está limitado en el nombre de las variables de entorno a las que pasa cmd. Deben ser nombres de variables de shell válidos y no deben ser de solo lectura o variables especiales para el shell.
Por ejemplo, no puedes hacer:
1=foo cmd
O
+++=bar cmd
bash no te permite hacer:
SHELLOPTS=xtrace cmd
Si bien puedes hacer:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(no es que quieras o debas querer hacer eso). O:
env SHELLOPTS=xtrace cmd
(A veces necesito hacer eso).
Tenga en cuenta que con envusted todavía no puede pasar una cadena de variable de entorno que no contenga un =(no es que tampoco quiera hacerlo).
Un uso de enves permitir la $PATHbúsqueda de ejecutables en líneas shebang (porque envconsidera $PATHcuando busca el ejecutable). Esto es útil si el ejecutable que desea invocar puede estar en diferentes lugares en diferentes máquinas. Por ejemplo,
#!/usr/bin/env perl
en la primera línea de un script con conjunto de bits ejecutable ejecutará este script con Perl sin importar si está instalado en /usr/bin/perlo en/usr/local/bin/perl o en un lugar completamente diferente, siempre que el directorio esté en la ruta.
Por supuesto, esa búsqueda de ruta conlleva un riesgo adicional, pero el riesgo no es mayor que si hubiera escrito explícitamente perl yourscript.pl, lo que también busca perl en la ruta de búsqueda.
Otro momento en el que enves realmente útil es si desea controlar el entorno por completo. Ejecuto un programa de servidor (Informix, en caso de que no pueda adivinar) cuyo entorno quiero controlar por completo. Lo ejecuto usando enval final de un script que establece un montón de variables con los valores correctos:
La -iopción elimina el entorno existente. Las VAR=valueopciones posteriores establecen las variables de entorno que quiero establecer; el nombre del programa está en $ONINIT, y cualquier argumento de línea de comando se pasa literalmente con "$@".
La ${IXH:+INFORMIXSQLHOSTS="$IXH"}construcción solo pasa INFORMIXSQLHOSTS="$IXH"a envsi $IXHse establece en un valor no vacío.
Respuestas:
Son funcionalmente equivalentes.
La principal diferencia es que
env FOO=bar bazimplica invocar un proceso intermedio entre el shell ybaz, donde al igual que conFOO=bar bazel shell, invoca directamentebaz.Por lo tanto, en ese sentido,
FOO=bar bazse prefiere.Las únicas situaciones en las que me encuentro usando
env FOO=bares donde tengo que pasar un comando a otro comando.Como ejemplo específico, digamos que tengo un script de contenedor que realiza algunas modificaciones del entorno y luego invoca
execel comando que se le pasó, como:Si lo ejecutas como
myscript FOO=bar baz,execarrojará un error comoexec FOO=bar bazno válido.En cambio, lo llama como
myscript env FOO=bar bazque se ejecuta comoexec env FOO=bar baz, y es perfectamente válido.fuente
FOO=bar exec bazembargo, puede hacerlo , por lo que no necesitaenven su último punto.execalgo, ¿utiliza su entorno actual?sudo FOO=bar bazpasar variables de entorno sin necesidad de hacerloenv.FOO=barel script. SiFOOno es siemprebar, no quiero a codificar ella, y en su lugar lo paso en.exec, comoFOO=bar exec baz.En este ejemplo en particular, no existe una diferencia efectiva, suponiendo que su shell es un shell compatible con POSIX, y suponiendo que
bazes un ejecutable y no un shell incorporado.Si su shell no es compatible con POSIX, por ejemplo ,
cshotcshla sintaxisno funciona y no hay una sintaxis de shell equivalente. Para esas conchas, el
envcomando es la única forma de anular o inyectar variables de entorno para un solo comando.Si
bazes un shell integrado, digamos,fcpor ejemplo,envno dará los mismos resultados, porqueenvestá ejecutando un nuevo proceso en lugar de ser ejecutado directamente por el shell del comando. Además, no hay unfcejecutable, solo puede ejecutarse como un shell integrado debido a la forma en que interactúa con el entorno del shell, y también loenvhará nunca funcionará con un tipo incorporadofc.Además,
envofrece la-iopción, que le permite iniciar un comando en un entorno vacío con solo un conjunto específico de variables de entorno. Porenvlo tanto, puede ser muy útil para iniciar procesos en entornos desinfectados, por ejemplofuente
tcsh, escribía(setenv FOO bar; baz)para obtener la función equivalente.Además de lo que ya se ha dicho
Al ser una función de shell (Bourne / POSIX), está limitado en el nombre de las variables de entorno a las que pasa
cmd. Deben ser nombres de variables de shell válidos y no deben ser de solo lectura o variables especiales para el shell.Por ejemplo, no puedes hacer:
O
bashno te permite hacer:Si bien puedes hacer:
(no es que quieras o debas querer hacer eso). O:
(A veces necesito hacer eso).
Tenga en cuenta que con
envusted todavía no puede pasar una cadena de variable de entorno que no contenga un=(no es que tampoco quiera hacerlo).fuente
Un uso de
enves permitir la$PATHbúsqueda de ejecutables en líneas shebang (porqueenvconsidera$PATHcuando busca el ejecutable). Esto es útil si el ejecutable que desea invocar puede estar en diferentes lugares en diferentes máquinas. Por ejemplo,en la primera línea de un script con conjunto de bits ejecutable ejecutará este script con Perl sin importar si está instalado en
/usr/bin/perlo en/usr/local/bin/perlo en un lugar completamente diferente, siempre que el directorio esté en la ruta.Por supuesto, esa búsqueda de ruta conlleva un riesgo adicional, pero el riesgo no es mayor que si hubiera escrito explícitamente
perl yourscript.pl, lo que también busca perl en la ruta de búsqueda.fuente
Otro momento en el que
enves realmente útil es si desea controlar el entorno por completo. Ejecuto un programa de servidor (Informix, en caso de que no pueda adivinar) cuyo entorno quiero controlar por completo. Lo ejecuto usandoenval final de un script que establece un montón de variables con los valores correctos:La
-iopción elimina el entorno existente. LasVAR=valueopciones posteriores establecen las variables de entorno que quiero establecer; el nombre del programa está en$ONINIT, y cualquier argumento de línea de comando se pasa literalmente con"$@".La
${IXH:+INFORMIXSQLHOSTS="$IXH"}construcción solo pasaINFORMIXSQLHOSTS="$IXH"aenvsi$IXHse establece en un valor no vacío.fuente