Respostas:
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 execve
manual:
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
environ
aponta para uma matriz de ponteiros para seqüências de caracteres chamadas "ambiente". A última ponteiro nesta matriz tem o valorNULL
. (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
exec*e
variantes que passam explicitamente um env, em vez de usar implicitamente a environ
variável global. O v
meio "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.
Você entendeu um pouco errado: SOME_NAME=value
cria uma variável de shell (na maioria dos shells). export SOME_NAME=value
cria 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/exec
método de iniciar um novo processo usado por todos os Unixes. Quando você export
possui 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 exec
comando 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=value
seqüências de caracteres, consulte a environ(7)
página de manual). Outro estado que é herdado inclui ulimit
configuraçõ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 exec
processo recém- editado.
Consulte a bash
descriçã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 cd
em 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_PATH
e 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.
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.
SOME_NAME=value command
se 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".
fork()
ed, mas eles fazem receber (cópias de) variáveis do shell.
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 crontab
ou visudo
você pode definir a EDITOR
variá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 man
comando que examina seu PAGER
ambiente 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 PATH
variá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_HOME
variá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
, HISTFILE
etc), 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).
"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 ... ↑
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.
Substituímos os envários por a $
e letras maiúsculas . Por exemplo: $PS1
.
Podemos imprimir um envar desta maneira:
echo $PS1
$PS1
manté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 $PS1
veremos os valores de \u
, \w
mais 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 $PS1
trará:
Hello, I'm your prompt >
No Bash 4.xx, podemos imprimir TODOS os envios no sistema com o env
comando Sugiro executar env
no terminal e dar uma olhada na saída.
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.
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:
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/profile
embora também possamos fazer isso, é .bashrc
claro.
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 bash
em 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.
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 $MESSAGE
uma sub-sessão, seja do seu usuário ou de outro, ela será impressa.
Observe que as variáveis internas do Shell, como PS1
não devem ser exportadas, mas se você deseja exportá-las por qualquer motivo e elas não aparecerem, não execute bash
depois export
, mas sim bash –norc
.
$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 ~
.
No Bash 4.xx, quando usamos um utilitário sem o caminho completo, o sistema utilizará todos os 6 valores mencionados acima, do $PATH
envar. Então, ele começará /user/local/bin
e seguirá todo o seu conteúdo procurando pelo echo
executá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 $PATH
envar, é instalar executáveis que não estão sob nenhum de seus valores nativos.
Depois de instalar esses executáveis, devemos definir seu $PATH
valor de acordo e podermos trabalhar com eles.
$PATH
:Podemos export $PATH
basear 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/John
para $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/profile
e pelo nome .bashrc
.
!
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.
warning about ! in an environment variable value not working that is right below an example showing it working
? Por favor exemplo.
quite bizarre advice about what to do after exporting a shell variable
, o que exatamente você quer dizer?
false notion of global environment variables
, o que exatamente você quer dizer?
exec(3)
família (ou seja, aqueles que não correspondem ao exec * v) passam ** pelo ambiente oculto.