Eu vi perguntas relacionadas como essa , mas elas não fornecem a resposta exata para minha pergunta
Dos meus experimentos, bem como desta resposta , printenv
e env
praticamente mostro o mesmo conjunto de variáveis do sistema.
Se eu definir as variáveis em
/etc/bash.bashrc (deve ser para variáveis de sistema em todo o sistema)
SYSTEM_ENVI=1000
~/.bashrc (supostamente para variáveis de sistema específicas do usuário)
USER_ENVI=10
Eu até fiz logout e login para que o /etc/environment entre em vigor. Ocorre o seguinte cenário:
$echo $SYSTEM_ENVI
//outputs 1000
$echo $USER_ENVI
//outputs 10
$CURR_ENVI=1
$env | grep USER_ENVI
//nothing shows up, the same if I grepped SYSTEM_ENVI or CURR_ENVI
$set | grep USER_ENVI
//shows up USER_ENVI assignment, the same if I grepped SYSTEM_ENVI or CURR_ENVI
Minhas perguntas são:
- Quais variáveis do sistema fazem
printenv
/env
imprimem? - Deve-se usar
set
para ver todas as variáveis acessíveis (variável de sistema e variável local) em vez deprintenv
ouenv
?
Quanto à justificativa de não duplicação
No que me diz respeito, esta pergunta e a resposta marcada me ajudaram a perceber os fatos que:
- Variáveis de shell não são variáveis de ambiente
- As atribuições em /etc/bash.bashrc ou ~/.bashrc não criam variáveis de ambiente, mas instruem os processos interativos que não são do shell de login para criar e inicializar essas variáveis do shell nas inicializações.
Acho que minha pergunta não é necessariamente diferente desta, mas ler a resposta marcada nessa não me satisfaz tanto quanto a resposta dada neste post.
env
eprintenv
estão imprimindo a lista de strings de ambiente (destinadas a conter definições de variáveis de ambiente) que são fornecidas a eles pelo comando que as executa. O chamador eventualmente fará um:chamada de sistema where
argv
eenvp
são duas listas de strings.env
/printenv
apenas imprime a lista de strings emenvp
, uma por linha.Por convenção, as strings em
envp
estão no formatovar=value
, mas não precisam ser (não conheço nenhumaexecve()
implementação que o aplique) e a maioria dasenv
implementaçõesprintenv
não se importam quando as exibem.Quando o chamador for um shell POSIX, ele incluirá no
envp
que ele passar paraenv
a lista de suas variáveis de shell marcadas para exportação (ou porque o usuário chamouexport
/typeset -x
nele, ou porque a variável já estava no ambiente que o shell recebido na inicialização).Se algumas das variáveis de ambiente que o shell recebeu na inicialização não puderem ser mapeadas para uma variável do shell, ou se alguma das
envp
strings recebidas não contiver um=
caractere, dependendo da implementação do shell, essas strings serão passadas intocados, ou a casca irá arrancá-los ou alguns deles.Exemplo com
bash
, usando GNUenv
para passar uma lista de nomes de variáveis arbitrárias (env
mas não pode passar strings envp arbitrárias, elas têm que conter a=
, e as que usamsetenv()
não podem passar algumas que começam com=
¹).(a variável com o nome vazio foi removida, mas não as outras).
Além disso, se o shell recebeu várias
envp
strings para o mesmo nome de variável, dependendo do shell, todas elas serão passadas adiante, ou apenas a primeira, ou apenas a última.set
em shells POSIX imprime a lista de variáveis de shell, incluindo as não escalares para shells que suportam tipos de array/hash, sejam elas marcadas para exportação ou não.Em shells POSIX você também pode usar
export -p
para listar as variáveis que foram marcadas para exportação. Ao contrário deenv
/printenv
, também lista as variáveis que foram marcadas para exportação, mas ainda não receberam nenhum valor.Em shells do tipo Korn como
ksh
,zsh
oubash
, você também pode usartypeset
para obter mais informações, incluindo atributos de variáveis, e listar variáveis por tipo (comotypeset -a
listar as variáveis de matriz).Aqui, adicionando
USER_ENVI=10
ao seu~/.bashrc
, você está configurando as invocações interativas sem login dobash
shell para definir uma variável deUSER_ENVI
shell na inicialização. Como você não usouexport
, essa variável permanece uma variável de shell (a menos que estivesse no ambiente quandobash
iniciada), portanto não é passada como variáveis de ambiente para comandos executados por esse shell./etc/environment
, em si, no Ubuntu 16.04 é lido pelopam_env.so
módulo de autenticação conectável. Os aplicativos que fazem login comologin
,sshd
,lightdm
lerão esses arquivos se configurados para usarpam_env.so
e/etc/pam.d
passarão as variáveis de ambiente correspondentes (nada a ver com variáveis de shell aqui) para o comando que eles iniciam em seu nome após a autenticação (como seu shell de login paralogin
/sshd
, ou seu gerenciador gráfico de sessão paralightdm
...).Como o ambiente é herdado por padrão, quando seu gerenciador de sessão executa um emulador de terminal que, por sua vez, executa seu shell de login, essas variáveis de ambiente serão passadas em cada etapa e seu shell as mapeará para variáveis de shell que você pode expandir no comando linha com coisas como
echo "$VAR"
.pam_env
env/etc/environment
se parecem com scripts de shell, maspam_env
não invoca um shell para analisá-los e entende apenas um subconjunto da sintaxe do shell e só permite definir variáveis cujo nome seja feito de um ou mais caracteres alfanuméricos ASCII ou sublinhados (não permitem que você defina uma123
variável que não seja um nome de variável shell POSIX válido).¹, para passar uma lista de strings de env arbitrárias, você também pode chamar
execve()
diretamente como com:aqui testando com
zsh
em vez debash
Fazendo:
Você está configurando uma variável, mas não uma variável de ambiente. Para isso você precisa:
Ou
É razoável que isso não funcione para você:
Não há nenhuma variável de ambiente chamada
SYSTEM_ENVI
set. Não há nada sobre/etc/environment
isso que possamos dizer, pois você não postou seu conteúdo (nem parece estar usando).O que
env
vai imprimir é exatamente o mesmo queprintenv
deve imprimir (sem opções).Respostas:
Ambos env e printenv relatarão exatamente a mesma lista de variáveis realmente configuradas se não houver opções ou lista de variáveis após o comando.
Você pode usar set (sem opções) para ver todas as variáveis definidas. Isso não significa que você deve usá-lo. Depende do que você quer listar. É perfeitamente válido e correto listar apenas a lista de variáveis de ambiente.