Desativar uma variável de ambiente para um comando


24

Eu posso correr ENV_VAR=value commandpara executar commandcom um valor específico para ENV_VAR. Qual é o equivalente a unset ENV_VARpara command?


7
Além: commandé uma escolha infeliz de espaços reservados, pois na verdade existe um comando interno com esse nome. mycommandou somecommandisso pode ser um hábito melhor para entrar.
Charles Duffy

@CharlesDuffy, eu costumo usar cmdpara isso.
Stéphane Chazelas

Respostas:


35

Além da -iopção, que limpa todo o ambiente, o POSIX envnão fornece nenhuma maneira de desmarcar uma variável.

No entanto, com algumas envimplementações (incluindo GNU, busybox'e FreeBSD, pelo menos), você pode:

env -u ENV_VAR command

O que funcionaria para remover todas as instâncias de uma ENV_VARvariável do ambiente (observe que ela não funciona para a variável de ambiente com um nome vazio ( env -u ''gera um erro ou é ineficaz dependendo da implementação, mesmo que todos aceitem env '=value', provavelmente uma limitação incorridos pela unsetenv()função C, que o POSIX requer para retornar um erro para a cadeia vazia, enquanto não houver essa limitação para putenv())).

Portably (em shells POSIX), você pode fazer:

(unset -v ENV_VAR; exec command)

(observe que, com alguns shells, usar execpode alterar o que commandé executado: executa o sistema de arquivos em vez de uma função ou um componente interno, por exemplo (e ignoraria a aliasexpansão obviamente), como envacima. Você gostaria de omitir esses casos) .

Mas isso não funcionará para variáveis ​​de ambiente que tenham um nome que não possa ser mapeado para uma variável de shell (observe que alguns shells, como mkshessas, tirariam essas variáveis ​​do ambiente na inicialização de qualquer maneira) ou variáveis ​​marcadas como somente leitura.

-vé para o shell Bourne e bashcujo unsetsem -vpoderia desabilitar uma ENV_VAR função se não houvesse variável com esse nome. A maioria dos outros shells não desabilita funções, a menos que você passe na -fopção. (improvável que faça diferença na prática).

(Também tenha cuidado com o bug / falha de bash/ mksh/ yashcuja unset, em algumas circunstâncias, pode não desmarcar a variável, mas revelar a variável em um escopo externo )

Se perlestiver disponível, você pode fazer:

perl -e 'delete $ENV{shift@ARGV}; exec @ARGV or die$!' ENV_VAR command

O que funcionará mesmo para a variável de ambiente com um nome vazio.

Agora, tudo isso não funcionará se você desejar alterar uma variável de ambiente para um builtin ou função e não desejar que eles sejam executados em um subshell, como em bash:

env -u LANG printf -v var %.3f 1.2 # would run /usr/bin/printf instead
(unset -v LANG; printf -v var %.3f 1.2) # changes to $var lost afterwards

(aqui desabilitar LANG como uma abordagem equivocada para garantir . seja usado e entendido como o separador decimal. Seria melhor usar LC_ALL=C printf...isso)

Com alguns shells, você pode criar um escopo local para a variável usando uma função:

without() {
  local "$1" # $1 variable declared as initially unset in bash¹
  shift
  "$@"
}
without LANG printf -v var %.3f 1.2

Com zsh, você também pode usar uma função anônima:

(){local ENV_VAR; command}

Essa abordagem não funcionará em alguns shells (como os baseados no shell Almquist), localque não declaram a variável como inicialmente desativada (mas herdam o valor e os atributos). Nessas, você pode fazer local ENV_VAR; unset ENV_VAR, mas não faça isso mkshou yash(em typesetvez localdisso), pois isso não funcionaria, unsetpois apenas cancelaria olocal .

¹ Também tenha cuidado que em bash , o local ENV_VAR(embora não definido) reteria o atributo de exportação . Portanto, se commandfosse uma função que atribui um valor ENV_VAR, a variável estará disponível no ambiente de comandos chamados posteriormente. unset ENV_VARlimparia esse atributo. Ou você pode usar o local +x ENV_VARque também garantiria uma lista limpa (a menos que essa variável tenha sido declarada somente leitura, mas não há nada que você possa fazer sobre isso bash).


11
É uma pergunta separada, mas que diabos é uma variável de ambiente com um nome vazio e como você a usaria - mesmo para algum tipo de exploração? Você não precisaria escrever um programa que leia o ambiente e procure algo parecido com isso?
Joe

@ Joe, tente por exemplo env '=foo' python -c 'import os; print os.environ[""]'. Não espero que muitas pessoas queiram definir uma variável assim.
Stéphane Chazelas

9

Não há equivalente direto, até onde eu saiba; você pode usar um subshell:

(unset ENV_VAR; exec command)

(unset ENV_VAR; exec somecommand)se você quiser ser equivalente ao original em eficiência (consumindo o subshell). Como é, isso adiciona um garfo extra.
Charles Duffy

11
@ Charles, de fato, embora alguns shells o façam automaticamente, pois esse commandé o último comando na invocação do subshell.
Stephen Kitt

+1 porque é fácil digitar para uso interativo. Eu uso subshells para alterações pontuais no ambiente de shell de uma linha, em vez de lembrar que é env -u.
Peter Cordes

0

Você pode usar ENV_VAR= command

Na verdade, isso não desmarca a variável, mas pode ser útil em muitos casos (os scripts de shell geralmente usam apenas test -npara verificar se uma variável está definida):

$ export ENV_VAR=foo
$ mycommand
ENV_VAR: foo
$ ENV_VAR=bar mycommand
ENV_VAR: bar
$ ENV_VAR= mycommand
ENV_VAR: 
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.