O shell embutido set
mostra todas as variáveis, não apenas aquelas que foram exportadas para o ambiente.
Se você quiser adicionar uma variável ao ambiente, basta fazer export variablename
no seu shell.
Estou usando o x86_64 GNU / Linux com bash
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
system("set > setc"); // A subset of '$ set'
return 0;
}
Eu posso ver que o arquivo setc contém um subconjunto de $ set
.
Estou curioso para saber como o shell (processo pai) decide o que fornecer ao processo filho e o que não fazer?
E se eu quiser fornecer mais variáveis de ambiente para o processo filho? Como se pode controlar isso?
O shell embutido set
mostra todas as variáveis, não apenas aquelas que foram exportadas para o ambiente.
Se você quiser adicionar uma variável ao ambiente, basta fazer export variablename
no seu shell.
Sob o capô, o modo como as variáveis de ambiente transitam de um programa para outro é através da execve
chamada do sistema , que carrega uma nova imagem de programa do disco. (Esta imagem substitui o programa atual; há outra chamada de sistema, fork
, que duplica o programa atual; como system
combinam fork
, execve
e algumas outras chamadas de sistema para iniciar um subprocesso.) Nesse nível baixo, um programa pode passar o que quiser para o programa sucessor.
No entanto, a maioria dos programas simplesmente transmite o ambiente que receberam quando começaram. Funções de biblioteca como system
leem variáveis globais que são inicializadas no ambiente inicial do programa; essa variável global pode ser modificada por outras funções da biblioteca, como putenv
. Se um programa não incluir código especificamente projetado para alterar o ambiente, ele transmitirá seu ambiente para seus subprocessos.
Em seu teste, você usou o comando shell set
. Este comando lista variáveis do shell, que são um superconjunto de variáveis de ambiente. O shell expõe todas as suas variáveis de ambiente como variáveis da linguagem de programação shell; Além disso, você pode definir mais variáveis. O comando interno export
usa o nome de uma variável de shell como um argumento e marca essa variável como exportada; variáveis marcadas como exportadas são adicionadas ao ambiente de subprocessos.
Em um shell interativo, geralmente há muitas variáveis de shell que não são exportadas. Um shell não interativo recém-iniciado tem menos. É por isso que você está vendo menos variáveis de system("set")
do que você vê no seu shell interativo. Se você observasse as variáveis de ambiente (com o comando env
ou export
sem argumento), você encontraria o mesmo (ou talvez mais algumas, dependendo do shell).
Depois de passar por man bash
, temos a imagem completa. Se eu tivesse lido homem antes de postar a pergunta! BTW acima de uma resposta não parece correta enquanto outra fica aquém para esclarecer. Então:
O shell possui um ambiente de execução, que consiste em arquivos abertos herdados pelo shell na invocação, a máscara do modo de criação de arquivo, parâmetros shell herdados do pai do shell no ambiente etc. (Para mais detalhes man bash
EXECUÇÃO DE COMANDO AMBIENTE) .)
Os coins = declare
e set
quando invocados sem argumentos, cuspem os valores de todas as variáveis (no formato nome = valor) presentes no ambiente do shell. (Observe que a saída de set
e declare
compreende uma parte do ambiente de shells.)
Agora, quando um comando simples que não seja uma função interna ou shell deve ser executado, ele é invocado em um ambiente de execução separado que consiste em arquivos abertos do shell, máscara de modo de criação de arquivo, variáveis de shell e funções marcadas para exportação (um subconjunto de variáveis e funções no ambiente do shell) etc. Se tentarmos executar esse comando, então, como disse Gilles na resposta acima, "Se um programa não incluir código especificamente projetado para mudar o ambiente, ele transmitir seu ambiente para seus subprocessos ".
Então, quando tentamos executar o programa acima, o programa recebe um subconjunto do ambiente do shell. Então quando dizemos system ("set > setrc") o sistema () cria um processo filho (que é shell BTW) e então o shell filho executa set > setrc
. Ao fazer isso, o programa transmite seu ambiente (versão reduzida do ambiente do shell pai) para o processo filho (execução do shell set
). Agora, quando set > setrc
é executado, ele imprime os valores de todas as variáveis (no formato nome = valor) presentes na chamada do ambiente do shell, que é uma versão reduzida do ambiente do shell pai. É por isso que o conteúdo reduzido de setrc.
Podemos cotrolar os parâmetros e funções a serem passados pelo Bash para um comando com a ajuda de export
e declare -x
. ( man bash
seção AMBIENTE.)
Como os outros já mencionaram export
e env
, apenas para esclarecer: export
e env
(sem argumentos) imprime o ambiente a ser passado para o subprocesso (ou comando) e NÃO o ambiente do shell enquanto set
e declare
mostra todas as variáveis no ambiente do shell . E é por isso que você pode fazer echo de $ VAR_NAME (qualquer variável presente em set
ou declare
output, apesar de NÃO estar em env
ou export
output).