Qual é a diferença entre o comando
$ env FOO=bar baz
e
$ FOO=bar baz
Que efeito envtem?
Qual é a diferença entre o comando
$ env FOO=bar baz
e
$ FOO=bar baz
Que efeito envtem?
Respostas:
Eles são funcionalmente equivalentes.
A principal diferença é que env FOO=bar bazenvolve a invocação de um processo intermediário entre o shell e baz, onde, como FOO=bar bazo shell, invoca diretamente baz.
Então, a esse respeito, FOO=bar bazé o preferido.
As únicas situações em que me encontro usando env FOO=baré onde tenho que passar um comando para outro comando.
Como exemplo específico, digamos que eu tenha um script de wrapper que execute algumas modificações no ambiente e, em seguida, chame execo comando que foi passado para ele, como:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Se você executá-lo como myscript FOO=bar baz, o execerro exec FOO=bar bazserá inválido.
Em vez disso, você o chama como o myscript env FOO=bar bazque é executado como exec env FOO=bar baze é perfeitamente válido.
FOO=bar exec bazisso, para não precisar envno seu último ponto.
execusa algo, ele usa seu ambiente atual?
sudo FOO=bar bazpassar variáveis de ambiente sem a necessidade env.
FOO=baro script. Se FOOnem sempre é bar, não quero codificá-lo e passá-lo para dentro.
exec, como FOO=bar exec baz.
Neste exemplo em particular, não há diferença efetiva, supondo que seu shell seja um shell compatível com POSIX e assumindo que bazseja um executável e não um shell embutido.
Se seu shell não for um shell compatível com POSIX, por exemplo , cshou tcsha sintaxe
FOO=bar baz
não funciona e não há sintaxe de shell equivalente. Para esses shells, o envcomando é a única maneira de substituir ou injetar variáveis de ambiente para um único comando.
Se bazfor um shell embutido, digamos, fcpor exemplo, envnão dará os mesmos resultados, porque envestá executando um novo processo em vez de ser executado diretamente pelo shell de comando. Além disso, não existe um fcexecutável, ele só pode ser executado como um shell embutido por causa da maneira como ele interage com o ambiente do shell e, portanto env, nunca funcionará com um embutido como esse fc.
Além disso, envoferece a -iopção, que permite iniciar um comando em um ambiente vazio com apenas um conjunto especificado de variáveis de ambiente. Portanto, envpode ser muito útil para iniciar processos em ambientes higienizados, por exemplo
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcsh, escrevia (setenv FOO bar; baz)para obter a função equivalente.
Além do que já foi dito
VAR=value cmd args > redirs
sendo um recurso shell (Bourne / POSIX), você está limitado no nome das variáveis de ambiente às quais passa cmd. Eles precisam ser nomes de variáveis válidos do shell e não devem ser somente leitura ou variáveis especiais para o shell.
Por exemplo, você não pode fazer:
1=foo cmd
Ou
+++=bar cmd
bash não permite que você faça:
SHELLOPTS=xtrace cmd
Enquanto você pode fazer:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(não que você queira ou deva fazer isso). Ou:
env SHELLOPTS=xtrace cmd
(Às vezes eu preciso fazer isso).
Observe que envvocê ainda não pode passar uma sequência de variáveis de ambiente que não contenha um =(não que você queira fazer isso também).
Um uso de envé permitir a $PATHpesquisa de executáveis em linhas shebang (porque envconsidera a $PATHpesquisa ao executável). Isso é útil se o executável que você deseja chamar estiver em locais diferentes em máquinas diferentes. Por exemplo,
#!/usr/bin/env perl
na primeira linha de um script com conjunto de bits executável, ele será executado com Perl, independentemente de estar instalado /usr/bin/perlem /usr/local/bin/perlou em um local completamente diferente, desde que o diretório esteja no caminho.
É claro que a pesquisa de caminho traz um risco adicional, mas, então, o risco não é maior do que se você tivesse escrito explicitamente perl yourscript.pl, o que também procura perl no caminho de pesquisa.
Outro momento em que envé realmente útil é se você deseja controlar o ambiente completamente. Eu corro um programa de servidor (Informix, caso você não consiga adivinhar) cujo ambiente eu quero controlar completamente. Eu o executo envno final de um script que define um monte de variáveis com os valores corretos:
env -i HOME="$IXD" \
INFORMIXDIR="$IXD" \
INFORMIXSERVER="$IXS" \
${IXC:+INFORMIXCONCSMCFG="$IXC"} \
${IXH:+INFORMIXSQLHOSTS="$IXH"} \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG="onconfig.$IXS" \
PATH="/bin:/usr/bin:$IXD/bin" \
SHELL=/bin/ksh \
TZ=UTC0 \
$ONINIT "$@"
A -iopção zaps o ambiente existente. As VAR=valueopções subseqüentes definem as variáveis de ambiente que eu quero definir; o nome do programa está $ONINITe todos os argumentos da linha de comando são passados literalmente com "$@".
A ${IXH:+INFORMIXSQLHOSTS="$IXH"}construção passa apenas INFORMIXSQLHOSTS="$IXH"para envse $IXHestiver definida como um valor não vazio.