Que variáveis de ambiente / variáveis de shell fazem env e printenv mostram [duplicado]

1

Eu vi perguntas relacionadas, como esta , mas eles não fornecem a resposta exata para minha pergunta

De minhas experiências, bem como esta resposta , printenv e env praticamente mostram o mesmo conjunto de variáveis do sistema.

Se eu definir as variáveis em

  1. /etc/bash.bashrc (supostamente para variáveis do sistema em todo o sistema)

    SYSTEM_ENVI=1000
    
  2. ~ / .bashrc (supostamente para variáveis do sistema específicas do usuário)

    USER_ENVI=10
    

Eu até efetuei logout e login para que o / etc / environment tenha efeito. O cenário a seguir ocorre:

$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:

  1. Quais variáveis do sistema fazem printenv / env print?
  2. Deve-se usar set para ver todas as variáveis acessíveis (variável de sistema e variável local) em vez de printenv ou env ?

Em relação à justificação não duplicada

Tanto quanto eu estou preocupado, esta pergunta e a resposta marcada me ajudaram a perceber os fatos que:

  1. As variáveis do shell não são variáveis de ambiente
  2. Atribuições em /etc/bash.bashrc ou ~ / .bashrc não criam variáveis de ambiente, mas instruem os processos interativos não-login-shell para criar e inicialize estas variáveis da shell em startups.

Acho que minha pergunta não é necessariamente diferente de este mas ler a resposta marcada não satisfaz tanto quanto a resposta dada neste post.

    
por Tran Triet 17.09.2018 / 14:38

2 respostas

3

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 .

O

/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

    
por 17.09.2018 / 14:49
1

Ao fazer:

USER_ENVI=10

Você está configurando uma variável, mas não uma variável de ambiente. Para isso você precisa:

export USER_ENVI=10

Ou

USER_ENVI=10; export USER_ENVI

É razoável que isso não funcione para você:

$ env | grep SYSTEM_ENVI

Não há nenhuma variável de ambiente chamada SYSTEM_ENVI set. Não há nada sobre /etc/environment que possamos dizer, já que você não postou seu conteúdo (nem parece estar usando).

O que env imprimirá é exatamente o mesmo que printenv deve imprimir (sem opções).

Respostas:

  1. Ambas env e printenv irão reportar exatamente a mesma lista de variáveis realmente definidas iif não há opções ou lista de variáveis após o comando.

  2. 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ê deseja listar. É perfeitamente válido e correto listar apenas a lista de variáveis de ambiente.

por 17.09.2018 / 22:21