O Linux /proc/<pid>/environ
não é atualizado (como eu o entendo, o arquivo contém o ambiente inicial do processo).
Como posso ler o ambiente atual de um processo ?
fonte
O Linux /proc/<pid>/environ
não é atualizado (como eu o entendo, o arquivo contém o ambiente inicial do processo).
Como posso ler o ambiente atual de um processo ?
/proc/$pid/environ
atualiza se o processo alterar seu próprio ambiente. Mas muitos programas não se incomodam em mudar seu próprio ambiente, porque é um pouco inútil: o ambiente de um programa não é visível através dos canais normais, apenas através /proc
e ps
, e nem todas as variantes unix possuem esse tipo de recurso, portanto, os aplicativos não dependem nele.
No que diz respeito ao kernel, o ambiente aparece apenas como o argumento da execve
chamada do sistema que inicia o programa. O Linux expõe uma área na memória /proc
e alguns programas atualizam essa área, enquanto outros não. Em particular, acho que nenhum shell atualiza essa área. Como a área tem um tamanho fixo, seria impossível adicionar novas variáveis ou alterar o tamanho de um valor.
PATH=foo
em um shell não significa que ele será modificado*envp
. Em alguns shells, isso atualizou apenas uma estrutura de dados interna e é o código de execução do programa externo que é atualizado*envp
. Olheassign_in_env
emvariables.c
na fonte bash, por exemplo.fork
libc fará asys_fork
chamada usando o ambiente alocado para heap para o processo filho.argv
são mais comuns, mas ambos existem).Você pode ler o ambiente inicial de um processo em
/proc/<pid>/environ
.Se um processo alterar seu ambiente, para ler o ambiente, você deve ter a tabela de símbolos para o processo e usar a
ptrace
chamada do sistema (por exemplo, usandogdb
) para ler o ambiente a partir dachar **__environ
variável global . Não há outra maneira de obter o valor de qualquer variável de um processo Linux em execução.Essa é a resposta. Agora, para algumas anotações.
O exposto acima pressupõe que o processo seja compatível com POSIX, o que significa que o processo gerencia seu ambiente usando uma variável global
char **__environ
conforme especificado nas especificações de referência .O ambiente inicial de um processo é passado para o processo em um buffer de tamanho fixo na pilha do processo. (O mecanismo usual que faz isso é
linux//fs/exec.c:do_execve_common(...)
.) Como o tamanho do buffer é calculado para não exceder o tamanho necessário para o ambiente inicial, você não pode adicionar novas variáveis sem apagar as variáveis existentes ou esmagar a pilha. Portanto, qualquer esquema razoável para permitir mudanças no ambiente de um processo usaria o heap, onde a memória em tamanhos arbitrários pode ser alocada e liberada, o que é exatamente o que o GNUlibc
(glibc
) faz por você.Se o processo for utilizado
glibc
, ele será compatível com POSIX,__environ
sendo declarado noglibc//posix/environ.c
Glibc inicializado__environ
com um ponteiro para a memória que émalloc
do heap do processo e copia o ambiente inicial da pilha para essa área de heap. Cada vez que o processo usa asetenv
função,glibc
faz umrealloc
para ajustar o tamanho da área que__environ
aponta para acomodar o novo valor ou variável. (Você pode baixar o código-fonte da glibc comgit clone git://sourceware.org/git/glibc.git glibc
). Para realmente entender o mecanismo, você também precisará ler o código Hurdhurd//init/init.c:frob_kernel_process()
(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).Agora, se o novo processo for
fork
editado apenas , sem umaexec
substituição subsequente da pilha, a magia de cópia de argumento e ambiente será concluídalinux//kernel/fork.c:do_fork(...)
, onde ascopy_process
chamadas de rotinadup_task_struct
que alocam a pilha do novo processo chamandoalloc_thread_info_node
, chamasetup_thread_stack
(linux//include/linux/sched.h
) para o novo processo usandoalloc_thread_info_node
.Finalmente, a
__environ
convenção POSIX é uma convenção de espaço do usuário . Não tem conexão com nada no kernel do Linux. Você pode escrever um programa de espaço do usuário sem usarglibc
e sem o__environ
global e, em seguida, gerenciar as variáveis de ambiente da maneira que desejar. Ninguém o prenderá por fazer isso, mas você terá que escrever suas próprias funções de gerenciamento de ambiente (setenv
/getenv
) e seus próprios wrappers,sys_exec
e é provável que ninguém seja capaz de adivinhar onde você colocou as alterações em seu ambiente.fonte
/proc/[pid]/
parecem ter uma codificação estranha (alguém pode saber o que e por quê). Para mim, simplesmentecat environ
imprimiria as variáveis de ambiente em um formato realmente difícil de ler.cat environ | strings
resolveu isso para mim.Ele é atualizado à medida que o processo adquire / exclui suas variáveis de ambiente. Você tem uma referência informando que o
environ
arquivo não foi atualizado para o processo em seu diretório de processo em / proc filesystem?ou
ou
O
ps
texto acima imprimirá as variáveis de ambiente do processo no formato de saída, o processamento de texto (análise / filtragem) é necessário para ver as variáveis de ambiente como uma lista.Solaris (não solicitado, mas para referência vou postar aqui):
ou
EDIT: / proc / pid / environ não é atualizado! Eu estou corrigido. O processo de verificação está abaixo. No entanto, os filhos dos quais o processo é submetido à bifurcação herdam a variável de ambiente do processo e ela é visível em seu respectivo arquivo / proc / self / environment. (Use strings)
Com no shell: aqui xargs é um processo filho e, portanto, herda a variável de ambiente e também reflete em seu
/proc/self/environ
arquivo.Verificando-o de outra sessão, em que o terminal / sessão não é o processo filho do shell em que a variável de ambiente está definida.
Verificando de outro terminal / sessão no mesmo host:
terminal1:: Observe que printenv é fork e é um processo filho do bash e, portanto, lê seu próprio arquivo environment.
terminal2: no mesmo host - não o inicie no mesmo shell em que a variável acima foi definida, inicie o terminal separadamente.
fonte
export foo=bar
na sessão de uma festa (pid xxxx), depois façocat /proc/xxxx/environ | tr \\0 \\n
na sessão de outra festa e não vejofoo
.gdb
o pid, mas ainda não há referência lá. O bloco de variáveis de ambiente na memória é realocado sempre que há uma alteração e não está refletindo no arquivo de ambiente de seu próprio processo no sistema de arquivos proc, mas, no entanto, permite ser herdado pelo processo filho. Isso significa que é mais fácil saber detalhes intrínsecos quando o fork ocorre, como o processo filho obtém as variáveis de ambiente copiadas como estão.Bem, o seguinte não está relacionado às reais intenções do autor, mas se você realmente deseja "LER"
/proc/<pid>/environ
, pode tentaro que é melhor que
cat
isso.fonte
strings
. Mantenha simples.xargs --null
.tr '\0' '\n' < /proc/$$/environ | ...