É uma pergunta secundária, mas como é o próprio recurso chamado quando você define uma variável de ambiente para um único subcomando como esse? Sempre tive dificuldade em encontrar informações sobre isso, porque não sei como se chama.
John Cromartie
1
@JohnCromartie, você deve fazer isso como uma pergunta.
@JohnCromartie É um componente opcional de todos os comandos do shell, por isso está na seção "Comandos Simples" da maioria dos manuais de shell. Para o POSIX, isso estaria aqui . A Glenn vinculou a seção análoga do manual do bash para você.
Jw013
Definir uma variável que não existe por meio de uma atribuição cria uma variável de shell. A configuração via ENV ou a exportação da variável empurram a variável para o ambiente de execução do shell. Alterar o valor de uma variável existente atualizará o valor do ambiente de execução, se houver, caso contrário, altere-o nas variáveis internas do shell.
21414 Johan
Respostas:
26
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.
Você pode fazer FOO=bar exec bazisso, para não precisar envno seu último ponto.
Stéphane Chazelas
Quando você execusa algo, ele usa seu ambiente atual?
Glenn Jackman
1
Ditto @StephaneChazelas, e você também pode sudo FOO=bar bazpassar variáveis de ambiente sem a necessidade env.
Mike Miller
1
@StephaneChazelas que só funciona se eu quiser colocar FOO=baro script. Se FOOnem sempre é bar, não quero codificá-lo e passá-lo para dentro.
Patrick
@glennjackman sim, desde que as variáveis sejam exportadas ou passadas antes do exec, como FOO=bar exec baz.
22314 Patrick
14
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
Quando eu costumava usar tcsh, escrevia (setenv FOO bar; baz)para obter a função equivalente.
Barmar 21/05
6
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:
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.
Respostas:
Eles são funcionalmente equivalentes.
A principal diferença é que
env FOO=bar baz
envolve a invocação de um processo intermediário entre o shell ebaz
, onde, comoFOO=bar baz
o shell, invoca diretamentebaz
.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
exec
o comando que foi passado para ele, como:Se você executá-lo como
myscript FOO=bar baz
, oexec
erroexec FOO=bar baz
será inválido.Em vez disso, você o chama como o
myscript env FOO=bar baz
que é executado comoexec env FOO=bar baz
e é perfeitamente válido.fonte
FOO=bar exec baz
isso, para não precisarenv
no seu último ponto.exec
usa algo, ele usa seu ambiente atual?sudo FOO=bar baz
passar variáveis de ambiente sem a necessidadeenv
.FOO=bar
o script. SeFOO
nem sempre ébar
, não quero codificá-lo e passá-lo para dentro.exec
, comoFOO=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
baz
seja um executável e não um shell embutido.Se seu shell não for um shell compatível com POSIX, por exemplo ,
csh
outcsh
a sintaxenão funciona e não há sintaxe de shell equivalente. Para esses shells, o
env
comando é a única maneira de substituir ou injetar variáveis de ambiente para um único comando.Se
baz
for um shell embutido, digamos,fc
por exemplo,env
não dará os mesmos resultados, porqueenv
está executando um novo processo em vez de ser executado diretamente pelo shell de comando. Além disso, não existe umfc
executável, ele só pode ser executado como um shell embutido por causa da maneira como ele interage com o ambiente do shell e, portantoenv
, nunca funcionará com um embutido como essefc
.Além disso,
env
oferece a-i
opção, que permite iniciar um comando em um ambiente vazio com apenas um conjunto especificado de variáveis de ambiente. Portanto,env
pode ser muito útil para iniciar processos em ambientes higienizados, por exemplofonte
tcsh
, escrevia(setenv FOO bar; baz)
para obter a função equivalente.Além do que já foi dito
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:
Ou
bash
não permite que você faça:Enquanto você pode fazer:
(não que você queira ou deva fazer isso). Ou:
(Às vezes eu preciso fazer isso).
Observe que
env
você 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).fonte
Um uso de
env
é permitir a$PATH
pesquisa de executáveis em linhas shebang (porqueenv
considera a$PATH
pesquisa ao executável). Isso é útil se o executável que você deseja chamar estiver em locais diferentes em máquinas diferentes. Por exemplo,na primeira linha de um script com conjunto de bits executável, ele será executado com Perl, independentemente de estar instalado
/usr/bin/perl
em/usr/local/bin/perl
ou 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.fonte
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 executoenv
no final de um script que define um monte de variáveis com os valores corretos:A
-i
opção zaps o ambiente existente. AsVAR=value
opções subseqüentes definem as variáveis de ambiente que eu quero definir; o nome do programa está$ONINIT
e todos os argumentos da linha de comando são passados literalmente com"$@"
.A
${IXH:+INFORMIXSQLHOSTS="$IXH"}
construção passa apenasINFORMIXSQLHOSTS="$IXH"
paraenv
se$IXH
estiver definida como um valor não vazio.fonte