Se os processos herdam o ambiente do pai, por que precisamos exportar?

60

Eu li aqui que a finalidade de export em um shell é disponibilizar a variável para sub-processos iniciados a partir do shell.

No entanto, também li aqui e aqui que "Os processos herdam seu ambiente de seus pais (o processo que os iniciou)."

Se este for o caso, por que precisamos de export ? O que estou perdendo?

As variáveis do shell não fazem parte do ambiente por padrão? Qual a diferença?

    
por Amelio Vazquez-Reina 19.05.2014 / 17:23

3 respostas

58

Sua suposição é que as variáveis do shell são no ambiente . Isso está incorreto. O comando export é o que define um nome para estar no ambiente. Assim:

a=1 b=2
export b

resulta no shell atual sabendo que $a se expande para 1 e $b para 2, mas os subprocessos não sabem nada sobre a porque não faz parte do ambiente (mesmo no shell atual).

Algumas ferramentas úteis:

  • set : Útil para visualizar os parâmetros atuais do shell, exportados ou não
  • set -k : define argumentos atribuídos no ambiente. Considere f() { set -k; env; }; f a=1
  • set -a : Informa ao shell para colocar qualquer nome que seja definido no ambiente. Como colocar export antes de cada tarefa. Útil para arquivos .env , como em set -a; . .env; set +a .
  • export : Diz ao shell para colocar um nome no ambiente. Exportação e atribuição são duas operações totalmente diferentes.
  • env : Como um comando externo, env só pode informar sobre o ambiente herdado , portanto, é útil para verificação de integridade.
  • env -i : útil para limpar o ambiente antes de iniciar um subprocesso.

Alternativas para export :

  1. name=val command # Atribuição antes de o comando exportar esse nome para o comando.
  2. declare/local -x name # Exporta nome, particularmente útil em funções de shell quando você deseja evitar a exposição do nome ao escopo externo.
  3. set -a # Exporta todas as atribuições a seguir.
por 19.05.2014 / 17:38
21

Há uma diferença entre variáveis de shell e variáveis de ambiente. Se você definir uma variável de shell sem export ing, ela não será adicionada ao ambiente de processos e, portanto, não será herdada para seus filhos.

Usando export , você diz ao shell para adicionar a variável shell ao ambiente. Você pode testar isso usando printenv (que apenas imprime seu ambiente para stdout , já que é um processo-filho que você vê o efeito de variáveis export ing):

#!/bin/sh

MYVAR="my cool variable"

echo "Without export:"
printenv | grep MYVAR

echo "With export:"
export MYVAR
printenv | grep MYVAR
    
por 19.05.2014 / 17:35
6

Uma variável, uma vez exportada, faz parte do ambiente. PATH é exportado no próprio shell, enquanto variáveis personalizadas podem ser exportadas conforme necessário. Usando algum código de configuração:

$ cat subshell.sh 
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='

Compare

$ cat test.sh 
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh 
PATH=/bin
foo=bar
PATH=/bin
foo=bar

com

$ cat test2.sh 
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh 
PATH=/bin
foo=bar
PATH=/bin

Como foo não é exportado pelo shell e test2.sh nunca o exportou, ele não fazia parte do ambiente de subshell.sh na última execução.

    
por 19.05.2014 / 17:36