Definindo uma variável com ou sem exportação


955

Para que serve export?

Qual é a diferença entre:

export name=value

e

name=value

4
Observe também tangencialmente que export name=valuenão é portátil. Dependendo do que exatamente você deseja, tente name=value; export nameuma solução portátil.
tripleee

Respostas:


1054

export torna a variável disponível para subprocessos.

Isso é,

export name=value

significa que o nome da variável está disponível para qualquer processo executado a partir desse processo de shell. Se você deseja que um processo faça uso dessa variável, use exporte execute o processo nesse shell.

name=value

significa que o escopo da variável é restrito ao shell e não está disponível para nenhum outro processo. Você usaria isso para (digamos) variáveis ​​de loop, variáveis ​​temporárias etc.

É importante observar que a exportação de uma variável não a torna disponível para processos-pai. Ou seja, especificar e exportar uma variável em um processo gerado não a torna disponível no processo que a iniciou.


105
Especificamente, a exportação disponibiliza a variável para os processos filhos por meio do ambiente.
Beano

15
Eu também acrescentaria que, se a exportação estiver em um arquivo que você "origina" (como. Filename), também a exporta para o seu ambiente de trabalho.
Rogerdpack 17/09/2013

6
@rogerdpack você não pode fazer isso sem exportar? gato> blá \ na = oi \ n. blá; eco $ a; gera 'oi' para mim.
David Winiecki

2
Bom, funciona mesmo sem a exportação. Então eu acho que quando adquirem um arquivo, se você usar exportação que será refletido em processos filhos, se você não só vai afetar o meio ambiente festa locais ...
rogerdpack

19
Há um caso extremo nisso; name=value command não fazer a variável disponível no sub-processo command.
Oliver Charlesworth

254

Para ilustrar o que as outras respostas estão dizendo:

$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar

bash-3.2$ 

9
Mais um exemplo para isto #al$ foobar="Whatever" bash
Alun 15/06

70

Outros responderam que a exportação disponibiliza a variável para subshells, e isso é correto, mas apenas um efeito colateral. Quando você exporta uma variável, ela a coloca no ambiente do shell atual (ou seja, o shell chama putenv(3)ou setenv(3)).
O ambiente de um processo é herdado entre exec, tornando a variável visível em subshells.

Editar (com perspectiva de 5 anos): esta é uma resposta boba. O objetivo da 'exportação' é fazer com que as variáveis ​​"estejam no ambiente de comandos executados posteriormente", sejam esses subconjuntos ou subprocessos. Uma implementação ingênua seria simplesmente colocar a variável no ambiente do shell, mas isso impossibilitaria a implementação export -p.


6
Observe que isso não é inteiramente verdade. Em bash, a exportação realmente adiciona a variável ao ambiente do shell atual, mas esse não é o caso dash. Parece-me que adicionar a variável ao ambiente do shell atual é a maneira mais simples de implementar a semântica export, mas esse comportamento não é obrigatório.
William Pursell

7
Não tenho certeza do que dashtem a ver com isso. O pôster original estava perguntando especificamente sobre bash.
Starfish

14
A pergunta está marcada, bashmas se aplica igualmente a qualquer variante de casca de bourne. Ser excessivamente específico e fornecer respostas que se aplicam apenas a bashum grande mal.
William Pursell

12
bashé o jQuery do shell.
Potherca

2
export makes the variable available to subshells, and that is correctEste é um uso muito confuso da terminologia. Subshells não precisam exportherdar variáveis. Subprocessos fazem.
Amit Naidu

62

Já foi dito que não é necessário exportar no bash ao gerar sub-conchas, enquanto outros disseram exatamente o oposto. É importante notar a diferença entre subshells (aqueles que são criados por (), ``, $()ou loops) e subprocessos (processos que são chamados pelo nome, por exemplo, um literal bashaparecendo em seu script).

  • Os subconjuntos terão acesso a todas as variáveis ​​do pai, independentemente do estado exportado.
  • Sub processos será única ver as variáveis exportadas.

O que é comum nessas duas construções é que nenhuma delas pode passar variáveis ​​de volta para o shell pai.

$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:

Há mais uma fonte de confusão: alguns pensam que subprocessos 'bifurcados' são os que não veem variáveis ​​não exportadas. Normalmente, fork () s é imediatamente seguido por exec () s, e é por isso que parece que o fork () é a coisa a procurar, enquanto na verdade é o exec (). Você pode executar comandos sem fork () primeiro com o execcomando, e os processos iniciados por esse método também não terão acesso a variáveis ​​não exportadas:

$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export

Observe que parent:desta vez não vemos a linha, porque substituímos o shell pai pelo execcomando, então não há mais nada para executar esse comando.


Eu nunca vi um loop que (por si só) criou um subshell; OTOH que um pipeline faz (sempre para peças diferentes da última, às vezes para a última, dependendo do shell, versão e opções). Backgrounding ( &) também cria um subshell.
Dave_thompson_085

E esses var=asdf bash -c 'echo $var'ou var=asdf exec bash -c 'echo $var'? A saída é asdf. A ;diferença faz se colocada após a definição da variável. Qual seria a explicação? Parece que var(sem ;) o subprocesso gerado de alguma forma, devido ao shell de origem não ter nada a ver com isso. echo $varimprime nada se executado na segunda linha. Mas um alinhado var=asdf bash -c 'echo $var'; echo $varasdf\nasdf.
4xy 13/07/19

31

export NAME=value para configurações e variáveis ​​que têm significado para um subprocesso.

NAME=value para variáveis ​​temporárias ou de loop privadas ao processo atual do shell.

Mais detalhadamente, exportmarca o nome da variável no ambiente que copia para um subprocesso e seus subprocessos na criação. Nenhum nome ou valor é copiado novamente do subprocesso.

  • Um erro comum é colocar um espaço ao redor do sinal de igual:

    $ export FOO = "bar"  
    bash: export: `=': not a valid identifier
  • Somente a variável exportada ( B) é vista pelo subprocesso:

    $ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
    A is . B is Bob
  • Alterações no subprocesso não alteram o shell principal:

    $ export B="Bob"; echo 'B="Banana"' | bash; echo $B
    Bob
  • As variáveis ​​marcadas para exportação têm valores copiados quando o subprocesso é criado:

    $ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
    [1] 3306
    $ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash 
    Subprocess 1 has B=Bob
    Subprocess 2 has B=Banana
    [1]+  Done         echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
  • Somente variáveis ​​exportadas se tornam parte do ambiente ( man environ):

     $ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
     BOB=Bob

Então, agora deve estar tão claro quanto o sol do verão! Agradecimentos a Brain Agnew, alexp e William Prusell.


12

export tornará a variável disponível para todos os shells bifurcados no shell atual.


11

Note-se que você pode exportar uma variável e depois alterar o valor. O valor alterado da variável estará disponível para processos filho. Depois que a exportação for definida para uma variável, você deve fazer export -n <var>para remover a propriedade

$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset

Obrigado, esta é exatamente a informação que eu estava procurando, porque vi um script que usava variáveis ​​de ambiente e depois as "reexportou" com um novo valor, e fiquei imaginando se era necessário.
Mike Lippert

8

Como você já deve saber, o UNIX permite que os processos tenham um conjunto de variáveis ​​de ambiente, que são pares de chave / valor, sendo chave e valor como cadeias. O sistema operacional é responsável por manter esses pares para cada processo separadamente.

O programa pode acessar suas variáveis ​​de ambiente através desta API UNIX:

  • char *getenv(const char *name);
  • int setenv(const char *name, const char *value, int override);
  • int unsetenv(const char *name);

Os processos também herdam variáveis ​​de ambiente dos processos pai. O sistema operacional é responsável por criar uma cópia de todos os "envares" no momento em que o processo filho é criado.

O Bash , entre outros shells, é capaz de definir suas variáveis ​​de ambiente mediante solicitação do usuário. É para isso que exportexiste.

exporté um comando do Bash para definir a variável de ambiente para o Bash. Todas as variáveis ​​definidas com este comando seriam herdadas por todos os processos que esse Bash criaria.

Mais sobre Meio ambiente em Bash

Outro tipo de variável no Bash é a variável interna. Como o Bash não é apenas um shell interativo, ele é, de fato, um interpretador de script, pois qualquer outro intérprete (por exemplo, Python) é capaz de manter seu próprio conjunto de variáveis. Deve-se mencionar que o Bash (diferente do Python) suporta apenas variáveis ​​de string.

A notação para definir variáveis ​​Bash é name=value. Essas variáveis ​​permanecem no Bash e não têm nada a ver com variáveis ​​de ambiente mantidas pelo sistema operacional.

Mais sobre parâmetros de shell (incluindo variáveis)

Também vale ressaltar que, de acordo com o manual de referência do Bash:

O ambiente para qualquer comando ou função simples pode ser aumentado temporariamente, prefixando-o com designações de parâmetros, conforme descrito em Parâmetros do Shell . Essas instruções de atribuição afetam apenas o ambiente visto por esse comando.


Para resumir:

  • exporté usado para definir variável de ambiente no sistema operacional. Essa variável estará disponível para todos os processos filhos criados pelo processo Bash atual para sempre.
  • A notação de variável bash (nome = valor) é usada para definir variáveis ​​locais disponíveis apenas para o processo atual de bash
  • A notação de variável bash que prefixa outro comando cria a variável de ambiente apenas para o escopo desse comando.

1
O bash vars não suporta tantos tipos quanto o Python, mas possui string, número inteiro e dois tipos de array ('indexado' / tradicional e 'associativo', que é semelhante ao awk array, perl hash ou Python dict). Outras conchas variam; única string é portátil .
Dave_thompson_085

7

A resposta aceita implica isso, mas eu gostaria de tornar explícita a conexão com os shell builtins:

Como já mencionado, exportdisponibilizará uma variável para o shell e os filhos. Se nãoexport for usada, a variável estará disponível apenas no shell, e somente os recursos internos do shell poderão acessá-lo.

Isso é,

tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin

3

Aqui está outro exemplo:

VARTEST="value of VARTEST" 
#export VARTEST="value of VARTEST" 
sudo env | grep -i vartest 
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}" 
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'  

Somente usando a exportação VARTEST, o valor de VARTEST está disponível no sudo bash -c '...'!

Para mais exemplos, consulte:


3

Dois dos criadores do UNIX, Brian Kernighan e Rob Pike, explicam isso em seu livro "O ambiente de programação UNIX". Google para o título e você encontrará facilmente uma versão em pdf.

Eles abordam variáveis ​​de shell na seção 3.6 e focam no uso do exportcomando no final dessa seção:

Quando você deseja tornar acessível o valor de uma variável em subconchas, o comando de exportação do shell deve ser usado. (Você pode pensar por que não há como exportar o valor de uma variável de um sub-shell para seu pai).


2

Apenas para mostrar a diferença entre uma variável exportada que está no ambiente (env) e uma variável não exportada que não está no ambiente:

Se eu fizer isso:

$ MYNAME=Fred
$ export OURNAME=Jim

somente $ OURNAME aparece no ambiente. A variável $ MYNAME não está no ambiente.

$ env | grep NAME
OURNAME=Jim

mas a variável $ MYNAME existe no shell

$ echo $MYNAME
Fred

1

Por padrão, as variáveis ​​criadas em um script estão disponíveis apenas para o shell atual; processos filhos (sub-shells) não terão acesso a valores que foram definidos ou modificados. Permitir que os processos filhos vejam os valores requer o uso do comando de exportação.


0

Embora não seja mencionado explicitamente na discussão, NÃO é necessário usar a exportação ao gerar um subshell a partir do bash, pois todas as variáveis ​​são copiadas no processo filho.


Por favor, explique como o que você está dizendo parece contradizer diretamente as respostas com os exemplos acima.
Mike Lippert

Este é o caminho certo se você não deseja que as variáveis ​​sejam exportadas globalmente, mas disponíveis apenas para o subprocesso! Obrigado.
Jtblin
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.