Respostas:
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 export
e 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.
name=value command
não fazer a variável disponível no sub-processo command
.
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$
al$ foobar="Whatever" bash
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
.
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.
dash
tem a ver com isso. O pôster original estava perguntando especificamente sobre bash
.
bash
mas se aplica igualmente a qualquer variante de casca de bourne. Ser excessivamente específico e fornecer respostas que se aplicam apenas a bash
um grande mal.
bash
é o jQuery do shell.
export makes the variable available to subshells, and that is correct
Este é um uso muito confuso da terminologia. Subshells não precisam export
herdar variáveis. Subprocessos fazem.
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 bash
aparecendo em seu script).
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 exec
comando, 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 exec
comando, então não há mais nada para executar esse comando.
&
) também cria um subshell.
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 $var
imprime nada se executado na segunda linha. Mas um alinhado var=asdf bash -c 'echo $var'; echo $var
dá asdf\nasdf
.
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, export
marca 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.
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
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 export
existe.
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 resposta aceita implica isso, mas eu gostaria de tornar explícita a conexão com os shell builtins:
Como já mencionado, export
disponibilizará 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
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:
bash-hackers.org/wiki/doku.php/scripting/processtree
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 export
comando 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).
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
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.
export name=value
não é portátil. Dependendo do que exatamente você deseja, tentename=value; export name
uma solução portátil.