Comando env: Executando Comandos com Ambiente Modificado

Comando env: Executando Comandos com Ambiente Modificado

O Que é o Comando env?

Conclusão: env é 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 funções principais:

  • Definir variáveis de ambiente temporariamente e executar um comando (env LANG=C date altera uma variável para aquela única invocação)
  • Listar o ambiente atual quando executado sem argumentos (mesmo que printenv)

Também é 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 / distribuições baseadas em RHEL e outras distribuições Linux comuns)
  • Algumas opções (-C / -S) dependem da versão do coreutils. Veja abaixo.

Por Que Usar env VAR=valor?

Conclusão: Porque você quer que uma variável se aplique a apenas um comando, sem torná-la permanente e sem poluir o shell atual. export persiste; env é de uso único.

Existem várias maneiras de executar um comando com uma variável alterada. Conheça as diferenças.

# (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 variável apenas para aquela única invocação. A forma (3), export, mantém a alteração para todos os comandos executados depois. Quando você quer "apenas desta vez" ou "não deixar a configuração para trás", escolha (1) ou (2).

Como (1) e (2) diferem

  • LANG=C date é sintaxe do shell (uma atribuição prefixada). O shell a interpreta.
  • env LANG=C date lanca o executável env separado, que constrói o ambiente em um processo filho e então executa date via exec.

Para uso interativo o resultado é o mesmo. env se torna necessário quando não há shell envolvido: linhas shebang, argumentos para APIs da família exec, ou quando se parte de um ambiente vazio.

Definir uma Variável Temporariamente e Executar

Conclusão: Escreva env NOME=valor comando args.... Liste múltiplas variáveis separadas por espaços.

# 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 várias variáveis de uma vez, liste-as em sequência:

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

Isolando erros relacionados ao locale

Em um ambiente não-inglês, mensagens de erro podem ser traduzidas e difíceis de pesquisar. Fixar mensagens em inglês com env LANG=C comando facilita a busca e o registro de problemas.

Executar com Ambiente Vazio (env -i)

Conclusão: env -i inicia o comando com todas as variáveis de ambiente herdadas removidas. É ideal para isolar problemas do tipo "funciona só na minha máquina".

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

Com -i (--ignore-environment), até o PATH não é herdado. Então sob -i você deve especificar o comando pelo caminho absoluto ou passar as variáveis necessárias explicitamente.

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

Sob env -i, variáveis como HOME, PATH e LANG ficam indefinidas. Se um script depende delas, pode se comportar de forma inesperada. Passar apenas as variáveis realmente necessárias é o padrão seguro.

Executar sem uma Variável Específica (env -u)

Conclusão: env -u NOME remove apenas aquela variável antes de executar o comando. Diferente de -i, que limpa tudo, use para desabilitar uma única variável.

# 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 variável. Permite testar a hipotese "talvez esta variável seja a culpada" sem editar nenhum arquivo de configuração.

Executar em um Diretório Diferente (env -C)

Conclusão: env -C DIR comando muda para o diretório 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) está disponível no coreutils 8.28 e posterior. Não está disponível em ambientes mais antigos. Verifique com env --version (veja abaixo).

Usando /usr/bin/env no Shebang

Conclusão: Um shebang como #!/usr/bin/env python3 encontra o interpretador através do PATH. Evita codificar um caminho absoluto do interpretador, tornando o script portável.

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

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

#!/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 múltiplos argumentos.

-S requer coreutils 8.30 ou posterior. O suporte também difere no macOS (BSD env), então verifique o ambiente alvo antes de usá-lo em scripts distribuídos.

env vs printenv vs set

Conclusão: env sem argumentos lista apenas variáveis de ambiente. Use set para todas as variáveis incluindo as do shell, e printenv NOME para uma única.

Objetivo Comando
Listar variáveis de ambiente env ou printenv
Mostrar uma variável de ambiente printenv PATH (env sozinho não filtra)
Incluir variáveis do shell também set (builtin do bash)
Definir temporariamente e executar env VAR=val cmd

Passar um único argumento como env PATH não 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".

Resolução de Problemas

Conclusão: Os tropeços comuns com env são "sem PATH após -i" e "-C / -S indisponível em sistema antigo." Uma verificação de versão resolve a maioria deles.

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

env trata o primeiro argumento sem = como um nome de comando. Você 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 não encontrado após env -i

-i também limpa o PATH. Especifique o PATH explicitamente como em env -i PATH=/usr/bin:/bin comando, ou forneça 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

Próximas Leituras