O Linux /proc/<pid>/environnão é atualizado (como eu o entendo, o arquivo contém o ambiente inicial do processo).
Como posso ler o ambiente atual de um processo ?
O Linux /proc/<pid>/environnão é atualizado (como eu o entendo, o arquivo contém o ambiente inicial do processo).
Como posso ler o ambiente atual de um processo ?
Respostas:
/proc/$pid/environatualiza 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 /proce 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 execvechamada do sistema que inicia o programa. O Linux expõe uma área na memória /proce 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=fooem 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. Olhe assign_in_envem variables.cna fonte bash, por exemplo.
forklibc fará a sys_forkchamada usando o ambiente alocado para heap para o processo filho.
argvsã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 ptracechamada do sistema (por exemplo, usando gdb) para ler o ambiente a partir da char **__environvariá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 **__environconforme 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 GNU libc( glibc) faz por você.
Se o processo for utilizado glibc, ele será compatível com POSIX, __environsendo declarado no glibc//posix/environ.cGlibc inicializado __environcom um ponteiro para a memória que é mallocdo heap do processo e copia o ambiente inicial da pilha para essa área de heap. Cada vez que o processo usa a setenvfunção, glibcfaz um reallocpara ajustar o tamanho da área que __environaponta para acomodar o novo valor ou variável. (Você pode baixar o código-fonte da glibc com git clone git://sourceware.org/git/glibc.git glibc). Para realmente entender o mecanismo, você também precisará ler o código Hurd hurd//init/init.c:frob_kernel_process()(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).
Agora, se o novo processo for forkeditado apenas , sem uma execsubstituição subsequente da pilha, a magia de cópia de argumento e ambiente será concluída linux//kernel/fork.c:do_fork(...), onde as copy_processchamadas de rotina dup_task_structque alocam a pilha do novo processo chamando alloc_thread_info_node, chama setup_thread_stack( linux//include/linux/sched.h) para o novo processo usando alloc_thread_info_node.
Finalmente, a __environconvençã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 usar glibce sem o __environglobal 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_exece é provável que ninguém seja capaz de adivinhar onde você colocou as alterações em seu ambiente.
/proc/[pid]/parecem ter uma codificação estranha (alguém pode saber o que e por quê). Para mim, simplesmente cat environimprimiria as variáveis de ambiente em um formato realmente difícil de ler. cat environ | stringsresolveu isso para mim.
Ele é atualizado à medida que o processo adquire / exclui suas variáveis de ambiente. Você tem uma referência informando que o environarquivo não foi atualizado para o processo em seu diretório de processo em / proc filesystem?
xargs --null --max-args=1 echo < /proc/self/environ
ou
xargs --null --max-args=1 echo < /proc/<pid>/environ
ou
ps e -p <pid>
O pstexto 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):
/usr/ucb/ps -wwwe <pid>
ou
pargs -e <pid>
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/environarquivo.
[centos@centos t]$ printenv | grep MASK
[centos@centos t]$ export MASK=NIKHIL
[centos@centos t]$ printenv | grep MASK
MASK=NIKHIL
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
MASK=NIKHIL
[centos@centos t]$ unset MASK
[centos@centos t]$ printenv | grep MASK
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
[centos@centos t]$
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.
[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$
terminal2: no mesmo host - não o inicie no mesmo shell em que a variável acima foi definida, inicie o terminal separadamente.
[centos@centos ~]$ echo $$
4436
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/self/environ | grep -i spidey
[centos@centos ~]$ strings -f /proc/2610/environ | grep -i spidey
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/2610/environ | grep -i spidey
[centos@centos ~]$
export foo=barna sessão de uma festa (pid xxxx), depois faço cat /proc/xxxx/environ | tr \\0 \\nna sessão de outra festa e não vejo foo.
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 tentar
strings /proc/<pid>/environ
o que é melhor que catisso.
strings. Mantenha simples.
xargs --null.
tr '\0' '\n' < /proc/$$/environ | ...