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