env e printenv estão imprimindo a lista de sequências de ambiente (destinadas a conter as definições de variáveis de ambiente) que são dadas a elas pelo comando que as executa. O chamador acabará por fazer um:
execve("/usr/bin/env", argv, envp);
chamada de sistema em que argv e envp são duas listas de strings.
env / printenv apenas imprime a lista de strings em envp , uma por linha.
Por convenção, as strings em envp estão no formato var=value , mas não precisam ser (não sei de nenhuma implementação execve() que a imponha) e a maioria env , As implementações de printenv não se importam quando são exibidas.
Quando o chamador é um shell POSIX, ele incluirá no envp que ele passa para env a lista de suas variáveis shell marcadas para export (porque o usuário chamou export / typeset -x , ou porque a variável já estava no ambiente que o shell recebeu no início).
Se algumas das variáveis de ambiente que o shell recebeu na inicialização não puderam ser mapeadas para uma variável do shell, ou se qualquer uma das strings envp recebidas não continham um caractere = , dependendo da variável Na implementação do shell, essas strings serão passadas intocadas, ou o shell as removerá ou a algumas delas.
Exemplo com bash , usando o GNU env para passar uma lista de nomes de variáveis arbitrárias ( env não pode passar sequências arbitrárias de envp, mas eles devem conter = e os que usam setenv() não pode passar alguns que começam com = ¹).
$ env -i '=foo' '1=x' '+=y' bash -c printenv
+=y
1=x
[...]
(a variável com o nome vazio foi removida, mas não as outras).
Além disso, se o shell receber várias strings envp para o mesmo nome de variável, dependendo do shell, elas serão repassadas, ou apenas a primeira, ou somente a última.
set em shells POSIX imprime a lista de variáveis shell, incluindo as não-escalares para shells que suportam tipos array / hash, tenham sido marcados 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 de env / printenv , isso também lista variáveis que foram marcadas para exportação, mas ainda não receberam nenhum valor.
Em shells semelhantes a Korn como ksh , zsh ou bash , você também pode usar typeset para obter mais informações incluindo atributos de variáveis e listar variáveis por tipo (como typeset -a para listar variáveis de matriz).
Aqui, adicionando USER_ENVI=10 ao seu ~/.bashrc , você está configurando as chamadas interativas que não são de login do shell bash para definir uma variável USER_ENVI shell no início acima. Como você não usou export , essa variável permanece uma variável de shell (a menos que estivesse no ambiente quando bash iniciou), portanto, ela não é passada como variáveis ambiente para comandos executados por esse shell .
/etc/environment , no Ubuntu 16.04, é lido pelo módulo de autenticação pam_env.so pluggable. Aplicativos que registram você como login , sshd , lightdm lerão esses arquivos se configurados para usar pam_env.so em /etc/pam.d e passarem as variáveis ambiente correspondentes (nada a ver com variáveis shell aqui) para o comando que eles iniciam em seu nome depois de você autenticar (como seu shell de login para login / sshd , ou seu gerenciador de sessão gráfico para lightdm ...).
Como o ambiente é herdado por padrão, quando o 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 transmitidas em cada etapa e seu shell as mapeará para variáveis de shell que puder expandir na linha de comando com coisas como echo "$VAR" .
pam_env env arquivos como /etc/environment parecem scripts de shell, mas pam_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 é feito de um ou mais caracteres alfanuméricos ASCII ou sublinhados (permite definir uma variável 123 , embora não seja um nome de variável de shell POSIX válido).
¹, para passar uma lista de cadeias de caracteres arbitrárias, você também pode chamar execve() diretamente como:
perl -e 'require "syscall.ph";
$cmd = "/bin/zsh";
$args = pack("p*x[p]", "sh", "-c", "printenv");
$env = pack("p*x[p]", "a=b", "a=c", "", "+=+", "=foo", "bar");
syscall(SYS_execve(), $cmd, $args, $env)'
aqui testando com zsh em vez de bash