Comando env: Executando Comandos com Ambiente Modificado

Comando env: Executando Comandos com Ambiente Modificado

O Que e o Comando env?

Conclusao: env e uma ferramenta do coreutils que executa um comando com ambiente modificado. Escrito como env VAR=valor comando, permite executar um comando em um ambiente diferente sem poluir o shell atual.

env tem duas funcoes principais:

  • Definir variaveis de ambiente temporariamente e executar um comando (env LANG=C date altera uma variavel para aquela unica invocacao)
  • Listar o ambiente atual quando executado sem argumentos (mesmo que printenv)

Tambem e amplamente usado na linha shebang de scripts (#!/usr/bin/env python3) para localizar um interpretador via PATH.

Ambiente para este artigo

  • GNU coreutils env (Ubuntu / Debian / distribuicoes baseadas em RHEL e outras distribuicoes Linux comuns)
  • Algumas opcoes (-C / -S) dependem da versao do coreutils. Veja abaixo.

Por Que Usar env VAR=valor?

Conclusao: Porque voce quer que uma variavel se aplique a apenas um comando, sem torna-la permanente e sem poluir o shell atual. export persiste; env e de uso unico.

Existem varias maneiras de executar um comando com uma variavel alterada. Conheca as diferencas.

# (1) Atribuicao temporaria do shell (sem env)
$ LANG=C date

# (2) Atribuicao temporaria via env
$ env LANG=C date

# (3) export (afeta todos os comandos posteriores, persistente)
$ export LANG=C
$ date

As formas (1) e (2) alteram a variavel apenas para aquela unica invocacao. A forma (3), export, mantem a alteracao para todos os comandos executados depois. Quando voce quer "apenas desta vez" ou "nao deixar a configuracao para tras", escolha (1) ou (2).

Como (1) e (2) diferem

  • LANG=C date e sintaxe do shell (uma atribuicao prefixada). O shell a interpreta.
  • env LANG=C date lanca o executavel env separado, que constroi o ambiente em um processo filho e entao executa date via exec.

Para uso interativo o resultado e o mesmo. env se torna necessario quando nao ha shell envolvido: linhas shebang, argumentos para APIs da familia exec, ou quando se parte de um ambiente vazio.

Definir uma Variavel Temporariamente e Executar

Conclusao: Escreva env NOME=valor comando args.... Liste multiplas variaveis separadas por espacos.

# Mostrar a data com o fuso horario temporariamente definido como UTC
$ env TZ=UTC date

# Forcar o locale C para obter mensagens em ingles (util para investigacao de logs)
$ env LANG=C ls /nonexistent
ls: cannot access '/nonexistent': No such file or directory

Para definir varias variaveis de uma vez, liste-as em sequencia:

$ env LANG=C LC_ALL=C TZ=UTC ./myscript.sh

Isolando erros relacionados ao locale

Em um ambiente nao-ingles, mensagens de erro podem ser traduzidas e dificeis de pesquisar. Fixar mensagens em ingles com env LANG=C comando facilita a busca e o registro de problemas.

Executar com Ambiente Vazio (env -i)

Conclusao: env -i inicia o comando com todas as variaveis de ambiente herdadas removidas. E ideal para isolar problemas do tipo "funciona so na minha maquina".

# Verificar o que resta (quase nada)
$ env -i env

Com -i (--ignore-environment), ate o PATH nao e herdado. Entao sob -i voce deve especificar o comando pelo caminho absoluto ou passar as variaveis necessarias explicitamente.

# PATH foi removido, entao passe apenas as variaveis necessarias
$ env -i PATH=/usr/bin:/bin LANG=C ./myscript.sh

Sob env -i, variaveis como HOME, PATH e LANG ficam indefinidas. Se um script depende delas, pode se comportar de forma inesperada. Passar apenas as variaveis realmente necessarias e o padrao seguro.

Executar sem uma Variavel Especifica (env -u)

Conclusao: env -u NOME remove apenas aquela variavel antes de executar o comando. Diferente de -i, que limpa tudo, use para desabilitar uma unica variavel.

# Desabilitar temporariamente configuracoes de proxy e testar a conexao
$ env -u http_proxy -u https_proxy curl https://example.com

-u (--unset) pode ser repetido para cada variavel. Permite testar a hipotese "talvez esta variavel seja a culpada" sem editar nenhum arquivo de configuracao.

Executar em um Diretorio Diferente (env -C)

Conclusao: env -C DIR comando muda para o diretorio indicado antes de executar o comando. Compacta cd DIR && comando em uma linha sem subshell.

$ env -C /var/log tail -n 20 syslog

-C (--chdir) esta disponivel no coreutils 8.28 e posterior. Nao esta disponivel em ambientes mais antigos. Verifique com env --version (veja abaixo).

Usando /usr/bin/env no Shebang

Conclusao: Um shebang como #!/usr/bin/env python3 encontra o interpretador atraves do PATH. Evita codificar um caminho absoluto do interpretador, tornando o script portavel.

#!/usr/bin/env python3
print("hello")

Escrever #!/usr/bin/python3 diretamente falha em sistemas onde o Python esta em outro lugar (/usr/local/bin, um virtualenv, etc.). #!/usr/bin/env python3 busca no PATH, usando o primeiro python3 encontrado no ambiente do usuario.

#!/usr/bin/env -S python3 -u

Para passar argumentos ao interpretador em uma linha shebang, use -S (--split-string). Um shebang normalmente permite apenas um argumento; -S divide a string em multiplos argumentos.

-S requer coreutils 8.30 ou posterior. O suporte tambem difere no macOS (BSD env), entao verifique o ambiente alvo antes de usa-lo em scripts distribuidos.

env vs printenv vs set

Conclusao: env sem argumentos lista apenas variaveis de ambiente. Use set para todas as variaveis incluindo as do shell, e printenv NOME para uma unica.

Objetivo Comando
Listar variaveis de ambiente env ou printenv
Mostrar uma variavel de ambiente printenv PATH (env sozinho nao filtra)
Incluir variaveis do shell tambem set (builtin do bash)
Definir temporariamente e executar env VAR=val cmd

Passar um unico argumento como env PATH nao imprime o valor: env o trata como um nome de comando e reporta "No such file or directory." Para ver apenas o valor, use printenv PATH ou echo "$PATH".

Resolucao de Problemas

Conclusao: Os tropecos comuns com env sao "sem PATH apos -i" e "-C / -S indisponivel em sistema antigo." Uma verificacao de versao resolve a maioria deles.

"env: '...': No such file or directory"

env trata o primeiro argumento sem = como um nome de comando. Voce recebe este erro de env LANG C date (falta um =) ou env PATH (tentando ler um valor). Certifique-se de que a forma seja NOME=valor.

Comando nao encontrado apos env -i

-i tambem limpa o PATH. Especifique o PATH explicitamente como em env -i PATH=/usr/bin:/bin comando, ou forneca o comando pelo caminho absoluto.

# Verificar a versao do env (para decidir se -C / -S estao disponiveis)
$ env --version | head -1
env (GNU coreutils) 9.4

Proximas Leituras