Desvincular uma variável de ambiente para um comando

21

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

    
por Alexey Romanov 28.08.2017 / 16:22

3 respostas

31

Com algumas implementações env (incluindo GNU's, busybox 'e FreeBSD's pelo menos), você pode fazer:

env -u ENV_VAR command

O que funcionaria na remoção de todas as instâncias de uma variável ENV_VAR no ambiente (observe que não funciona para a variável de ambiente com um nome vazio ( env -u '' fornece um erro ou é ineficaz dependendo do implementação, mesmo que todos aceitem env '=value' , provavelmente uma limitação incorrida pela função unsetenv() C que POSIX requer para retornar um erro para a cadeia vazia, enquanto não há tal limitação para putenv() )).

Portável (em shells POSIX), você pode fazer:

(unset -v ENV_VAR; exec command)

(observe que com alguns shells, usar exec pode alterar qual command é executado: executa o do sistema de arquivos em vez de uma função ou interno, por exemplo (e ignora alias expansão obviamente), como env acima. Você gostaria de omiti-lo nesses casos).

Mas isso não funcionará para variáveis de ambiente que tenham um nome que não seja mapeável para uma variável de shell (observe que alguns shells como mksh removeriam essas variáveis do ambiente na inicialização) ou variáveis que foram marcado como somente leitura.

-v é para o shell Bourne e bash cujo unset sem -v poderia cancelar a função ENV_VAR se não houvesse variável por aquele nome. A maioria das outras shells não desabilitaria funções a menos que você passe a opção -f . (improvável que faça diferença na prática).

(Cuidado também com o bug / má qualidade de bash / mksh / yash cujo unset , sob algumas circunstâncias, pode não desfazer a variável, mas revelar a variável em um escopo externo )

Se perl estiver disponível, você pode fazer:

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

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

Agora, todos eles não funcionarão se você quiser alterar uma variável de ambiente para um arquivo incorporado ou função e não quiser 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, desconfigurando o LANG como uma abordagem equivocada, garantindo que . seja usado e entendido como o separador decimal. Seria melhor usar LC_ALL=C printf... para 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), cujo local não declara a variável como inicialmente não definida (mas herda o valor e os atributos). Nesses, você pode fazer local ENV_VAR; unset ENV_VAR , mas não faça isso em mksh ou yash ( typeset em vez de local para esse) pois isso não funcionaria, o unset só cancelando o local .

¹ Tenha também em atenção que, em bash , o local ENV_VAR (apesar de não definido) manteria o atributo export . Portanto, se command fosse uma função que atribuísse um valor a ENV_VAR , a variável estaria disponível no ambiente de comandos chamados posteriormente. unset ENV_VAR limparia esse atributo. Ou você poderia usar local +x ENV_VAR , o que também garantiria um slate limpo (a menos que essa variável tenha sido declarada como somente leitura, mas não há nada que você possa fazer em bash ).

    
por 28.08.2017 / 16:43
10

Não há equivalente direto, tanto quanto eu sei; você pode usar um subshell:

(unset ENV_VAR; exec command)
    
por 28.08.2017 / 16:33
0

Você pode usar ENV_VAR= command

Isso não desabilita a variável, mas pode ser útil em muitos casos (scripts de shell geralmente usam test -n para 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: 
    
por 01.09.2017 / 03:21