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

O que é export para?

Qual é a diferença entre:

 export name=value 

e

 name=value 

   

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

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ê quiser que um processo faça uso dessa variável, use export e execute o processo a partir desse 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) variables ​​de loop, variables ​​temporárias etc.

É importante observar que exportar 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.

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$ 

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

Editar (com perspectiva de 5 anos): esta é uma resposta boba. O objective da ‘exportação’ é fazer com que as variables ​​”estejam no ambiente de comandos executados posteriormente”, sejam esses comandos subcasos ou subprocesss. Uma implementação ingênua seria simplesmente colocar a variável no ambiente do shell, mas isso tornaria impossível implementar a export -p .

Já foi dito que não é necessário exportar no bash ao gerar subcaus, enquanto outros dizem exatamente o oposto. É importante notar a diferença entre subshells (aqueles que são criados por () , `` , $() ou loops) e subprocesss (processos que são invocados por nome, por exemplo, um literal bash aparecendo em seu script). Subshells terão access a todas as variables ​​do pai, independentemente de seu estado exportado. Subprocessos, por outro lado, verão as variables ​​exportadas. O que é comum nessas duas construções é que nenhuma delas pode passar variables ​​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 os subprocesss ‘bifurcados’ são os que não veem variables ​​não exportadas. Normalmente fork () s são imediatamente seguidos por exec () s, e é por isso que parece que o fork () é a coisa a ser procurada, enquanto na verdade é o exec (). Você pode executar comandos sem fork () primeiro com o comando exec e os processos iniciados por este método também não terão access às variables ​​não exportadas:

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

Note que não vemos o parent: linha desta vez, porque substituímos o shell pai pelo comando exec , então não resta nada para executar esse comando.

export NAME=value para configurações e variables ​​que têm significado para um subprocess.

NAME=value para variables ​​temporárias ou de loop privadas para o processo de shell atual.

Em mais detalhes, a export marca o nome da variável no ambiente que copia para um subprocess e seus subprocesss após a criação. Nenhum nome ou valor é copiado de volta do subprocess.

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

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

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

     $ export B="Bob"; echo 'B="Banana"' | bash; echo $B Bob 
  • Variáveis ​​marcadas para exportação possuem valores copiados quando o subprocess é 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 variables ​​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! Obrigado a Brain Agnew, alexp e William Prusell.

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

Deve-se notar que você pode exportar uma variável e depois alterar o valor. O valor alterado da variável estará disponível para processos filhos. Depois que a exportação tiver sido definida para uma variável, você deverá export -n 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 variables ​​de ambiente, que são pares chave / valor, sendo chave e valor sendo strings. O sistema operacional é responsável por manter esses pares para cada processo separadamente.

O programa pode acessar suas variables ​​de ambiente por meio desta API do 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 variables ​​de ambiente dos processos pai. O sistema operacional é responsável por criar uma cópia de todos os “envars” no momento em que o processo filho é criado.

O Bash , entre outros shells, é capaz de definir suas variables ​​de ambiente sob solicitação do usuário. É para isso que existe export .

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

Mais sobre o ambiente no Bash

Outro tipo de variável no Bash é a variável interna. Como o Bash não é apenas um shell interativo, ele é, na verdade, um interpretador de scripts, assim como qualquer outro interpretador (por exemplo, Python) é capaz de manter seu próprio conjunto de variables. Deve ser mencionado que o Bash (ao contrário do Python) suporta apenas variables ​​de string.

Notação para definir variables ​​Bash é name=value . Essas variables ​​ficam dentro do Bash e não têm nada a ver com variables ​​de ambiente mantidas pelo sistema operacional.

Mais sobre parâmetros de shell (incluindo variables)

Também vale a pena notar que, de acordo com o manual de referência da Bash:

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


Para resumir:

  • export é usada para definir a variável de ambiente no sistema operacional. Esta 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 variables ​​locais disponíveis apenas para o processo atual de bash
  • A notação de variável Bash prefixando outro comando cria uma variável de ambiente apenas para o escopo desse comando.

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

Como já mencionado, a export disponibilizará uma variável para o shell e para os filhos. Se a export não for usada, a variável só estará disponível no shell e somente os integrantes do shell poderão acessá-la.

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 export VARTEST o valor de VARTEST está disponível em sudo bash -c ‘…’!

Para mais exemplos, veja:

Apenas para mostrar a diferença entre uma variável exportada 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 

então apenas $ OURNAME aparece no env. A variável $ MYNAME não está no env.

 $ env | grep NAME OURNAME=Jim 

mas a variável $ MYNAME existe no shell

 $ echo $MYNAME Fred 

Dois dos criadores do UNIX, Brian Kernighan e Rob Pike, explicam isso em seu livro “The UNIX Programming Environment”. Google para o título e você encontrará facilmente uma versão em pdf.

Eles abordam variables ​​de shell na seção 3.6 e enfocam o uso do comando de export no final dessa seção:

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

Embora não seja mencionado explicitamente na discussão, NÃO é necessário usar a exportação ao gerar um subshell de dentro do bash, já que todas as variables ​​são copiadas para o processo filho.

Por padrão, as variables ​​criadas dentro de um script estão disponíveis apenas para o shell atual; Processos filhos (sub-shells) não terão access aos valores que foram definidos ou modificados. Permitir que processos filho visualizem os valores requer o uso do comando de exportação.