Linux / Comando env: definir variáveis e executar programas

env executa um programa com variáveis de ambiente adicionadas, alteradas ou removidas, sem modificar o shell que o chamou. Sem um programa a executar, mostra o ambiente resultante. Os exemplos abaixo usam GNU Coreutils e Bash; opções como -C e -S precisam existir na versão instalada.

Uma variável de ambiente é um par nome/valor transmitido a um programa, como PATH, que indica diretórios de busca de executáveis. Para consultar valores, printenv costuma ser mais direto; para preparar o ambiente de uma execução, use env.

O que é o comando env?

Um processo recebe o ambiente do processo que o iniciou. env ajusta sua própria cópia e executa o programa solicitado; esse programa pode transmitir o ambiente aos seus descendentes. O shell original continua com seus próprios valores. Além disso, env procura um executável: não executa diretamente uma função ou um comando interno exclusivo do shell. O guia de type ajuda a distinguir esses casos.

Sintaxe básica

env [opções] [nome=valor]... [comando [argumentos]...]

A sinopse acima usa colchetes para partes opcionais; substitua os nomes indicados pelos valores reais. Opções vêm antes das atribuições e do comando. Sem comando, as duas linhas abaixo mostram o ambiente recebido; a segunda ordena as linhas para facilitar a leitura, mas não cria um formato seguro para analisar valores que contenham quebras de linha.

env
env | sort

O ambiente pode conter tokens e outros valores sensíveis. Não publique sua saída completa em logs, capturas ou pedidos de suporte. Nos testes, use apenas variáveis fictícias. Para ferramentas que precisam distinguir entradas com quebras de linha, GNU env -0 as separa pelo byte nulo (NUL), desde que o consumidor aceite esse formato.

Definir variáveis para um comando

Em uma pasta de teste vazia, execute o bloco abaixo. Ele cria start.sh, um script que apenas mostra variáveis e o diretório, e names.txt, uma lista de três nomes. noclobber impede sobrescrever arquivos regulares existentes; uma falha de criação encerra o bloco. Bash, cat, chmod e sort devem estar disponíveis.

(
  set -o noclobber
  cat > start.sh <<'EOF' || exit 1
#!/usr/bin/env bash
printf 'APP_ENV=%s\n' "${APP_ENV-<ausente>}"
printf 'DEBUG=%s\n' "${DEBUG-<ausente>}"
printf 'HOST=%s PORT=%s\n' "${HOST-<ausente>}" "${PORT-<ausente>}"
printf 'Diretório=%s\n' "$PWD"
EOF
  chmod u+x start.sh || exit 1
  printf '%s\n' zebra abacate Banana > names.txt || exit 1
  env APP_ENV=production ./start.sh
  env LC_ALL=C sort names.txt
)

O script mostra APP_ENV=production; as outras variáveis refletem o ambiente recebido. Em seguida, a lista sai na ordem Banana, abacate, zebra. LC_ALL=C força a localidade C apenas para sort; LANG=C sozinho pode ser sobreposto por LC_ALL ou LC_COLLATE já definidos. Os arquivos ficam na pasta para os exemplos seguintes, mas as atribuições de env não mudam as variáveis do shell chamador.

Depois do bloco, consulte o valor no shell com a linha seguinte. Se APP_ENV não estava exportada, GNU printenv não imprime um valor e retorna status 1; se já estava exportada, mostra o valor anterior. Quando uma variável solicitada existe, retorna 0. Consulte $? imediatamente após o comando para conferir o status.

printenv APP_ENV

Você pode passar várias atribuições antes do programa. Reutilizando start.sh, a linha abaixo deve mostrar HOST=127.0.0.1 PORT=8080 e DEBUG=1. Ela não inicia um servidor nem abre uma porta: o script de demonstração apenas imprime os valores. Se o mesmo nome aparecer mais de uma vez, prevalece a última atribuição.

env HOST=127.0.0.1 PORT=8080 DEBUG=1 ./start.sh

Comparar atribuição temporária e env

No Bash e em shells POSIX, uma atribuição antes de um programa externo também fornece uma variável só para aquela execução. Com names.txt criado acima, as duas formas abaixo devem produzir a mesma lista ordenada.

LC_ALL=C sort names.txt
env LC_ALL=C sort names.txt

Essa equivalência vale aqui para o programa externo sort. Uma atribuição isolada, um comando interno especial e uma função do shell têm regras próprias; não generalize a todos os comandos. env acrescenta recursos como limpar variáveis herdadas, remover nomes e mudar o diretório do programa executado.

Começar com um ambiente vazio: -i

env -i /usr/bin/printenv

-i, ou --ignore-environment, ignora as variáveis herdadas. Em um ambiente GNU/Linux comum, o exemplo com /usr/bin/printenv deve terminar sem listar variáveis. Isso ajuda a encontrar dependências ocultas, mas não isola o sistema de arquivos, a rede ou as permissões: não é uma sandbox. Um programa iniciado pode criar novas variáveis por conta própria.

Para uma execução real, reintroduza o que for necessário. A linha seguinte conserva o valor atual de HOME e define PATH e LANG; por isso imprime essas entradas, em ordem não garantida. "$HOME" é expandido pelo shell antes de env limpar o ambiente. O comando não atribui um novo valor a HOME no shell.

env -i PATH=/usr/bin:/bin HOME="$HOME" LANG=C /usr/bin/env

A ausência de PATH não tem um comportamento portátil de busca. Use um caminho absoluto conhecido ou defina os diretórios necessários explicitamente. Caminhos como /usr/bin/printenv e /usr/bin:/bin são exemplos para sistemas que realmente os possuem; verifique a instalação e as dependências do programa.

Remover uma variável: -u

env -u HTTP_PROXY curl https://example.com
env --unset=DEBUG ./start.sh

-u nome, ou --unset=nome, remove a variável do ambiente recebido pelo programa. A primeira linha exige curl e faz uma requisição HTTPS ao domínio reservado para exemplos; remover somente HTTP_PROXY não garante uma conexão sem proxy, pois https_proxy, HTTPS_PROXY e ALL_PROXY, entre outras configurações do curl, podem continuar ativos, conforme a documentação de variáveis de proxy do curl. Na segunda, o script mostra DEBUG=<ausente>.

Definir uma variável como uma string vazia é diferente de removê-la.

env DEBUG= ./start.sh
env -u DEBUG ./start.sh

No script fornecido, a primeira chamada mostra DEBUG=, com valor vazio; a segunda mostra DEBUG=<ausente>. O programa pode tratar esses estados de modo diferente. A variável no shell chamador continua como estava: env -u não equivale a executar unset no pai.

Executar em outro diretório: -C

env -C /srv/app ./start.sh
env --chdir=/srv/app APP_ENV=production ./start.sh

-C, ou --chdir, muda o diretório antes de executar o programa e não muda o diretório do shell chamador. Substitua /srv/app por uma pasta existente que contenha seu start.sh executável; use aspas se o caminho tiver espaços. A linha Diretório=... permite conferir o destino. Uma pasta inexistente faz env falhar sem executar o script. A opção é uma extensão GNU: confirme env --help no sistema de destino.

Opções usadas com frequência

Opção Descrição
-i, --ignore-environment Inicia com um ambiente limpo, ignorando o ambiente existente.
-u nome, --unset=nome Remove a variável especificada do ambiente.
-C diretório, --chdir=diretório Muda para o diretório especificado antes de executar o comando.
-S texto, --split-string=texto Divide a string em múltiplos argumentos. Principalmente usado para passar múltiplos argumentos em um shebang.
-0, --null Ao imprimir o ambiente, separa as entradas com um caractere NUL em vez de uma nova linha.

Confira env --version, env --help e o manual da implementação instalada. A existência de env não garante todas as opções desta tabela, especialmente em sistemas que usam outra implementação.

Usar /usr/bin/env no shebang

O shebang é a linha inicial que começa com #! e indica o interpretador de um arquivo executável. Salve o programa completo abaixo em hello.py; o shebang deve começar na primeira linha do arquivo, sem espaços antes dele. Para executá-lo, use chmod u+x hello.py e então ./hello.py. Com Python 3 disponível no PATH, a saída esperada é Olá.

#!/usr/bin/env python3
print("Olá")

Essa forma encontra python3 no PATH, o que é útil quando o interpretador fica em locais diferentes. Ela ainda pressupõe que /usr/bin/env exista e não fixa uma versão do Python. Em um serviço que exija um interpretador determinado, um caminho absoluto verificado pode dar maior previsibilidade.

Passar argumentos ao interpretador com -S

Em sistemas que tratam o restante do shebang como um único argumento, escrever apenas python3 -I após env pode fazê-lo procurar um programa com esse nome inteiro. GNU env -S separa essa sequência. Para testar, salve a versão completa abaixo em hello.py, alterando apenas a primeira linha, e execute novamente ./hello.py.

#!/usr/bin/env -S python3 -I
print("Olá")

-S precisa ser suportado pela implementação de env; o interpretador também precisa aceitar suas opções. Em Python 3, -I ativa o modo isolado, que ignora variáveis PYTHON* e exclui determinados diretórios da busca de módulos. A saída deste exemplo continua sendo Olá. Em sistemas sem -S, use um invólucro que invoque explicitamente o interpretador e seus argumentos; não suponha que toda opção possa ser reproduzida dentro do próprio script.

Variáveis do shell e variáveis de ambiente

No exemplo abaixo, os parênteses limitam as alterações a um subshell. unset garante que o nome fictício comece ausente, mesmo que já estivesse exportado antes. A primeira consulta não imprime valor e retorna 1; após export, a segunda imprime value e retorna 0.

(
  unset LOCAL_ONLY
  LOCAL_ONLY=value
  printenv LOCAL_ONLY

  export LOCAL_ONLY
  printenv LOCAL_ONLY
)

export marca uma variável para integrar o ambiente de programas executados depois. env recebe as variáveis já exportadas e as atribuições que você lhe fornece, não todas as variáveis privadas do shell. No exemplo, sair do subshell preserva o estado anterior de LOCAL_ONLY no chamador.

A referência de comandos Linux reúne ferramentas para consultar arquivos, processos e o ambiente de execução.

Comparar env e printenv

Categoria env printenv
Principal finalidade Executar comando no ambiente modificado Verificar o valor de uma variável de ambiente
Mostrar todo o ambiente Possível se o comando for omitido Possível se o nome da variável for omitido
Consultar uma variável Como não há formato dedicado, um filtro é necessário. É consultado diretamente como printenv HOME.
Adicionar ou remover variáveis Suportado. Não suportado.
Executar comando Suportado. Não suportado.

Cuidados em scripts e serviços

  • Não registre todo o ambiente, incluindo tokens, senhas e caminhos de chaves privadas.
  • Você deve considerar a possibilidade de expor segredos ao histórico do shell ou informações de processo se você escrever valores secretos diretamente em env NOME=VALOR comando.
  • Usar env -i pode resultar em comportamento diferente, pois caminhos de certificado, localidade e variáveis de proxy podem estar ausentes.
  • O /usr/bin/env no shebang é afetado pelo PATH, então certifique-se de que você pode confiar no executor e no ambiente.
  • Para ambientes de serviço, use as funções de configuração de ambiente explícitas do gerenciador de serviço sempre que possível.

Perguntas frequentes

As variáveis definidas com env permanecem no terminal atual?

Não. env NOME=VALOR comando modifica apenas o ambiente do programa iniciado e não altera as variáveis do shell chamador.

Qual é a diferença entre env e export?

export marca uma variável do shell atual para ser passada a programas executados posteriormente. env prepara o ambiente de uma execução específica sem modificar o shell chamador.

O comando não pode ser encontrado em env -i.

Isso pode ser porque o PATH existente também foi removido. Use o caminho absoluto do executável ou defina explicitamente o PATH necessário.

Documentação oficial