O que exatamente é uma variável de ambiente?

42

Eu sei que VARIABLE=valuecria uma variável de ambiente e export VARIABLE=valuea disponibiliza para processos criados pelo shell atual. envmostra as variáveis ​​de ambiente atuais, mas onde elas moram? O que compreende uma variável de ambiente (ou um ambiente , para esse assunto)?

Matt
fonte

Respostas:

29

Um ambiente não é tão mágico quanto parece. O shell o armazena na memória e passa para a execve()chamada do sistema. O processo filho o herda como um ponteiro de matriz chamado environ. Na página de execvemanual:

SINOPSE

   #include <unistd.h>

   int execve(const char *filename, char *const argv[],
              char *const envp[]);

argvé uma matriz de sequências de argumentos passadas para o novo programa.
Por convenção, a primeira dessas seqüências deve conter o nome do arquivo associado ao arquivo que está sendo executado. envpé uma matriz de seqüências de caracteres, convencionalmente no formato key = value, que são passadas como ambiente para o novo programa.

A página de environ(7)manual também oferece algumas dicas:

SINOPSE

   extern char **environ;

DESCRIÇÃO

A variável environaponta para uma matriz de ponteiros para seqüências de caracteres chamadas "ambiente". A última ponteiro nesta matriz tem o valor NULL. (Essa variável deve ser declarada no programa do usuário, mas é declarada no arquivo de cabeçalho <unistd.h>, caso os arquivos de cabeçalho venham da libc4 ou libc5, e caso venham da glibc e _GNU_SOURCE foi definido.) Essa matriz de strings é disponibilizada para o processo pela chamada exec (3) que iniciou o processo.

Ambas as páginas de manual GNU correspondem à especificação POSIX

jordanm
fonte
4
+1, provavelmente vale a pena notar que alguns membros da exec(3)família (ou seja, aqueles que não correspondem ao exec * v) passam ** pelo ambiente oculto.
RSU
5
Observe que não se trata de processos filhos (processos filhos herdam toda a memória de seus pais), mas de programas executados (no mesmo processo); portanto, é outra maneira de passar dados por uma chamada de sistema execve () (que, de outra forma, limpa a memória do processo).
Stéphane Chazelas
@ msw: são as exec*evariantes que passam explicitamente um env, em vez de usar implicitamente a environvariável global. O vmeio "vetor" e refere-se aos argumentos da linha de comando passados ​​como uma matriz (em vez de uma "lista" (função de tamanho variável)) execveé uma chamada do sistema, e todas as outras exec*funções são invólucros libc para ele.
Peter Cordes
19

Você entendeu um pouco errado: SOME_NAME=valuecria uma variável de shell (na maioria dos shells). export SOME_NAME=valuecria uma variável de ambiente. Para o melhor, para o pior, a maioria dos shells Unix / Linux / * BSD usa sintaxe idêntica ao acessar variáveis ​​de ambiente e variáveis ​​de shell.

Em um sentido mais amplo, um "ambiente" é apenas a informação que acompanha a execução do programa. Em programas C, você pode encontrar o ID do processo com uma getpid()chamada, em um programa shell você usaria um acesso variável: $$. O ID do processo é apenas parte do ambiente do programa. Eu acredito que o termo "ambiente" vem de alguns dos tópicos mais teóricos da ciência da computação, como modelar a execução de programas. Os modelos de execução de programas têm um ambiente "que contém as associações entre variáveis ​​e seus valores".

E esta última definição mais forte é o que é um "ambiente" para os shells Unix / Linux / * BSD: uma associação entre nomes ("variáveis") e seus valores. Para a maioria das conchas no estilo Unix, os valores são todos cadeias de caracteres, embora isso não seja tão rigoroso quanto costumava ser. Ksh, Zsh e Bash todos digitaram variáveis ​​atualmente. Até as definições de função shell podem ser exportadas.

O uso de um ambiente separado das variáveis ​​de shell simples envolve o fork/execmétodo de iniciar um novo processo usado por todos os Unixes. Quando você exportpossui um par de nome / valor, esse par de nome / valor estará presente no ambiente de novos executáveis, iniciados pelo shell com uma execve(2)chamada do sistema (geralmente seguindo a fork(2), exceto quando o execcomando do shell foi usado).

Após um execve(), a main()função do novo binário possui seus argumentos de linha de comando, o ambiente (armazenado como uma matriz de ponteiros terminados em NULL para var=valueseqüências de caracteres, consulte a environ(7)página de manual). Outro estado que é herdado inclui ulimitconfigurações, diretório de trabalho atual e quaisquer descritores de arquivos abertos para os quais o execve()chamador não tinha o FD_CLOEXEC definido. O estado atual do tty (eco ativado, modo bruto etc.) também pode ser considerado parte do estado de execução herdado por um execprocesso recém- editado.

Consulte a bashdescrição do manual do ambiente de execução para obter comandos simples (exceto funções internas ou shell).

O ambiente Unix é diferente de pelo menos alguns outros sistemas operacionais: os "léxicos" do VMS podem ser alterados por um processo filho, e essa alteração era visível no pai. Um VMS cdem um processo filho afetaria o diretório de trabalho do pai. Pelo menos em algumas circunstâncias, e minha memória pode estar falhando comigo.

Algumas variáveis de ambiente são bem conhecidos, $HOME, $PATH, $LD_LIBRARY_PATHe outros. Algumas são convencionais para um determinado sistema de programação, de modo que um shell pai pode passar muitas e muitas informações de propósito específico para algum programa, como um diretório temporário específico ou um ID de usuário e senha que não aparecem ps -ef. Programas CGI simples herdam muitas informações do servidor da web por meio de variáveis ​​de ambiente, por exemplo.

Bruce Ediger
fonte
1
Parece um pouco mais complicado ainda. No bash, pelo menos SOME_NAME=value command, definirá a variável de ambiente SOME_NAME para essa chamada de comando. Confusamente, não parece definir a variável shell com o mesmo nome.
Samuel Edwin Ward
2
Para ser mais preciso, as variáveis ​​de ambiente não são herdadas, mas explicitamente passadas de um shell para os programas que ele gera.
msw
2
@SamuelEdwinO motivo pelo qual você SOME_NAME=value commandse comporta de maneira contrária à sua expectativa é que é uma sintaxe especial que significa "adicione SOME_NAME ao ambiente passado ao comando, mas não altere as variáveis ​​desse shell".
msw
1
Fascinante, o link para o cálculo lambda / programação funcional. Essa é uma conexão interessante que faz muito sentido.
Matt
1
Parte disso não está totalmente certa. Por exemplo, subshells são subprocessos e deve ser fork()ed, mas eles fazem receber (cópias de) variáveis do shell.
Ruakh
7

As variáveis ​​de ambiente em sua forma mais bruta são apenas um conjunto de pares nome / valor. Conforme descrito na página de manual do bash ( man 1 bash) na seção AMBIENTE:

   When  a  program  is invoked it is given an array of strings called the
   environment.   This  is  a  list  of  name-value  pairs,  of  the  form
   name=value.

   The  shell  provides  several  ways  to manipulate the environment.  On
   invocation, the shell scans its own environment and creates a parameter
   for  each name found, automatically marking it for export to child pro-
   cesses.  Executed commands inherit the  environment.

Em termos práticos, permite definir o comportamento que é compartilhado ou exclusivo dos programas invocados no shell atual. Por exemplo, ao usar crontabou visudovocê pode definir a EDITORvariável de ambiente para definir outro editor diferente daquele que seu sistema usaria por padrão. O mesmo pode ser verdadeiro para coisas como o mancomando que examina seu PAGERambiente para descobrir com qual programa pager deve ser usado para exibir a saída da página de manual.

Muitos comandos unix leem o ambiente e, dependendo do que está definido, alteram sua saída / processamento / ação, dependendo deles. Alguns são compartilhados, outros são exclusivos do programa. A maioria das páginas de manual contém informações sobre como a variável de ambiente afeta o programa descrito.

Outras ilustrações práticas são para itens como sistemas com várias instalações do Oracle na mesma plataforma. Ao definir ORACLE_HOME, todo o conjunto de comandos oracle (conforme carregado na sua PATHvariável de ambiente) puxa configurações, definições, mapeamentos e bibliotecas desse diretório de nível superior. O mesmo vale para outros programas, como o java, com sua JAVA_HOMEvariável de ambiente.

o próprio bash possui muitas variáveis ​​de ambiente que podem alterar o comportamento de várias coisas, como histórico ( HISTSIZE, HISTFILEetc), tamanho da tela ( COLUMNS), conclusão da guia ( FIGNORE, GLOBIGNORE) localidade e codificação / decodificação de caracteres ( LANG, LC_*), prompt ( PS1.. PS4) e assim por diante (procure novamente o conhecimento na página de manual do bash).

Além disso, você pode escrever scripts / programas que usam suas próprias variáveis ​​de ambiente personalizadas (para passar configurações ou alterar a funcionalidade).

Drav Sloan
fonte
0

"Variáveis ​​de ambiente" são um conjunto de valores nomeados dinâmicos que podem afetar a maneira como os processos em execução se comportarão em um computador.

Eles fazem parte do ambiente operacional no qual um processo é executado. Por exemplo, um processo em execução pode consultar o valor da variável de ambiente TEMP para descobrir um local adequado para armazenar arquivos temporários, ou a variável HOME ou USERPROFILE para encontrar a estrutura de diretórios pertencente ao usuário que está executando o processo.

Mais informações aqui → http://en.wikipedia.org/wiki/Environment_variable .

Tudo o que você deseja saber sobre variáveis ​​de ambiente ... ↑

SoCalDiegoRob
fonte
1
Embora seja improvável que esses links desapareçam, é melhor responder à pergunta aqui com texto relevante e fornecer o link como um complemento para informações de backup.
Anthon
@Anthon Eu acredito que você está correto e vou fazer as mudanças assim que eu posso ... Obrigado pelo conselho ...
SoCalDiegoRob
-1

Esta resposta requer alguma experiência e conhecimento de script de shell com os termos variável, valor, substituição de variável, prompt, eco, kernel, shell, utilitário, sessão e processo.

Uma variável de ambiente (envar) é um conjunto de variáveis ​​definidas globalmente que podem afetar a maneira como um determinado processo se comportará no sistema operacional de um computador.

1. Uma introdução exemplar:

Substituímos os envários por a $e letras maiúsculas . Por exemplo: $PS1.

Podemos imprimir um envar desta maneira:

echo $PS1

$PS1mantém o valor do prompt do Unix. Digamos que seus valores nativos sejam \u \w $.

  • \u significa usuário (atual),
  • \w significa diretório de trabalho,
  • $ é delimitar o prompt.

Portanto, se fizermos:, echo $PS1veremos os valores de \u, \wmais o cifrão no final.

Poderíamos mudar o comportamento do Unix nesse contexto, se mudarmos os valores desse envar. Por exemplo:

PS1="\w >"

Agora, o prompt se parece com isso (assumindo que o diretório de trabalho seja chamado "John"):

John >

Da mesma maneira que poderíamos fazer PS1="Hello, I'm your prompt >", isso echo $PS1trará:

Hello, I'm your prompt >

No Bash 4.xx, podemos imprimir TODOS os envios no sistema com o envcomando Sugiro executar envno terminal e dar uma olhada na saída.

2. Como esses dados são mostrados e manipulados:

O terminal de uma sessão nos permite personalizar os envares que estão chegando com o Bash.

As alterações acima mencionadas são geralmente temporárias, e aqui está o porquê:

Cada sessão (que não é uma sub-sessão) é única e vários processos podem ser executados de maneira única ao mesmo tempo (cada um com seu próprio conjunto de envares), mas geralmente há herança da sessão 0 para a sessão 1 e superior.

As alterações que fazemos em um processo são exclusivas e cessarão se a fecharmos sem salvá-las de alguma maneira.

Então, como podemos salvar essas alterações:

Existem vários tipos de maneiras disponíveis para armazenar alterações no envar, dependendo do escopo escolhido. Aqui estão diferentes escopos (níveis) para essas alterações:

  • Nível do processo: os envares estão disponíveis apenas para programas na sessão atual.
  • Nível de exportação: os envares estão disponíveis para programas na sessão atual ou em todas as suas sub-sessões.
  • Nível global: as alterações serão armazenadas para todas as sessões (primária e todas as subs).

Onde os dados do envar são armazenados:

O Unix é composto de três camadas principais: Kernel, shell e utilitários. AFAIK cada shell possui seus próprios envios, e estes são criados principalmente ou exclusivamente no shell.

O local específico no qual alterar globalmente esses é geralmente, /etc/profileembora também possamos fazer isso, é .bashrcclaro.

3. Criando novos envios:

Podemos criar novos ambientes e aqui está um caminho; a partir do Bash 4.xx, não há enavar nativo nomeado MESSAGE(como dito, os envares geralmente são maiúsculos).

MESSAGE="Hello world!"

irá criá-lo para nós e agora, se digitarmos eco $MESSAGE, obteremos hello world!.

Se executarmos bashem nossa sessão de trabalho atual (janela), iniciaremos uma nova sub-sessão do bash e não trabalharemos mais no processo original, a menos que seja executada exit.

Nota: Em sistemas operacionais com um emulador de terminal (como a área de trabalho Ubuntu), uma sub-sessão geralmente é executada na mesma janela, mas uma nova sessão em outra janela não é uma sub-sessão da existente (é um processo adjacente ) .

Nota: Não use sinais especiais em valores de envar como! ou eles não serão salvos.

Exportando o envar da sessão original para todas as sub-sessões:

Ainda podemos usar o envar criado na primeira sessão, também na segunda, sem registrá-lo nos arquivos conf do usuário ou no nível global (consulte os dados a seguir). Veja como fazer isso:

Vá para a sessão original (na janela atual ou em outra) e execute:

export MESSAGE

ao exportar, não use um $sinal.

Agora é exportado para todas as sub-sessões. Se você fizer echo $MESSAGEuma sub-sessão, seja do seu usuário ou de outro, ela será impressa.

Observe que as variáveis ​​internas do Shell, como PS1não devem ser exportadas, mas se você deseja exportá-las por qualquer motivo e elas não aparecerem, não execute bashdepois export, mas sim bash –norc.

4. O envar $ PATH:

$PATH é o ambiente que os usuários geralmente mudam mais.

Se nós echo $PATH, vamos ver este fluxo:

/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Os valores impressos desse envar são separados por dois pontos (:), mas aqui está uma maneira potencialmente mais confortável (esses são os mesmos valores):

/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games

Esses são diretórios a serem procurados quando executamos um utilitário.

Ao executar which echo, obteremos o local do arquivo - por exemplo, podemos ver que ele existe /bin/echo.

Com base nisso, não precisamos digitar echo envar para visualizar os valores do evnar. Nós também podemos fazer:

/bin/echo $ENVAR

O envar ainda será executado, por exemplo:

/bin/echo $HOME

Nos dá

/home/User || /root

Assim como:

echo $HOME

Nos dá

/home/User || /root

Nota: $HOMEé abreviado como ~.

As relações system- $ PATH e uma possível interação do usuário:

No Bash 4.xx, quando usamos um utilitário sem o caminho completo, o sistema utilizará todos os 6 valores mencionados acima, do $PATHenvar. Então, ele começará /user/local/bine seguirá todo o seu conteúdo procurando pelo echoexecutável.

Nesse caso, ele irá parar em /bin/echo, no qual, nesse caso, o executável reside.

Portanto, a principal razão pela qual podemos personalizar o $PATHenvar, é instalar executáveis ​​que não estão sob nenhum de seus valores nativos.

Depois de instalar esses executáveis, devemos definir seu $PATHvalor de acordo e podermos trabalhar com eles.

5. Apêndice - expandindo $PATH:

Podemos export $PATHbasear sub-sessões (que inclui extensões bash como WP-CLI para WordPress ou Drush for Drupal) desta maneira:

export PATH="/home/John:$PATH"

Isto irá adicionar um novo valor /home/Johnpara $PATH, em seguida, logo em seguida, ele vai anexar quaisquer valores nativos para ele (direito após os dois pontos), que são armazenados sob a sintaxe $PATH.

Essa mudança permanente pode ser feita no script relevante, geralmente sob /etc/profilee pelo nome .bashrc.

JohnDoea
fonte
3
Há muita coisa errada nesta resposta: conflilação de sessões e processos, alertar sobre !um valor de variável de ambiente que não está funcionando logo abaixo de um exemplo mostrando que está funcionando, uma falsa noção de sub-sessões, conselhos bastante bizarros sobre o que fazer depois de exportar uma variável de shell e uma noção falsa de variáveis ​​de ambiente global.
JdeBP #
warning about ! in an environment variable value not working that is right below an example showing it working? Por favor exemplo.
31419 JohnDoea
quite bizarre advice about what to do after exporting a shell variable, o que exatamente você quer dizer?
31419 JohnDoea
false notion of global environment variables, o que exatamente você quer dizer?
precisa saber é o seguinte