Estou no Debian GNU/Linux 9. Eu sei que /proc
é especial , eu sei o que /proc/self
é .
Este comando
sh -c '/bin/cat /proc/self/comm - </proc/self/comm'
rendimentos
cat
sh
O padrão será semelhante se eu usar dash
em vez de sh
. Mas com bash
, ksh
ou zsh
o resultado é
cat
cat
Tomando /proc/self/stat
em vez de /proc/self/comm
posso confirmar que os dois cat
-s são de fato o mesmo processo único. Aparentemente, as conchas diferem sob o capô, tudo bem. Agora vamos pegar
sh -c '/bin/cat /proc/self/environ - </proc/self/environ'
Tendo observado o acima, com sh
ou dash
espero ver o ambiente do cat
primeiro, o ambiente do shell depois. Parece funcionar (ambos os ambientes provavelmente são idênticos de qualquer maneira, então é difícil dizer se tudo funciona como esperado, mas meu ponto é: nenhum environ
está vazio).
Com bash
, ksh
ou zsh
espero ver o ambiente das cat
duas vezes, mas só é impresso uma vez . Dividindo em dois casos separados:
bash -c '/bin/cat - </proc/self/environ'
não imprime nada, como seenviron
estivesse vazio;bash -c '/bin/cat /proc/self/environ'
imprime algo como esperado.
O que está acontecendo? Este não é o caso com comm
ou stat
. Por que é environ
diferente?
$ uname -a
Linux barbaz 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1 (2018-04-29) x86_64 GNU/Linux
As diferenças entre os shells são devido a diferenças na configuração do processo.
dash
configura redirecionamentos antes da bifurcação, então/proc/self
aponta para o shell;bash
ezsh
configurá-los após a bifurcação, então/proc/self
aponta para o novo processo. Você pode ver isso acontecer comstrace -f
:strace -f dash -c '/bin/cat /proc/self/comm - </proc/self/comm'
shows (entre muitas outras coisas)(
/proc/self/comm
é aberto antes daclone
chamada do sistema, que é onde o processo se bifurca);strace -f bash -c '/bin/cat /proc/self/comm - </proc/self/comm'
mostra(
/proc/self/comm
é aberto após aclone
chamada, no processo filho, 8106).Entender por que
environ
aparece vazio requer um pouco mais de explicação. Quando/proc/<pid>/environ
é aberto , o kernel salva uma cópia do ponteiro para o da tarefamm_struct
, que contém ponteiros para o ambiente. Masexecve
, que é usado para iniciar ocat
processo, cria um novomm_struct
para o processo . Assim o redirecionamento acaba apontando para informações obsoletas e aocat
ler sua entrada não vê seu ambiente real. O ambiente que ele vê deve ser uma cópia de seu pai, mas os shells envolvidos o limpam antes de bifurcar e configurar o novo ambiente (que é configurado porexecve
).