Por que o shebang leva a um nome de processo diferente de uma chamada explícita?

0

Resumo

Usando mirage como exemplo, um programa python que começa com um shebang:

#!/usr/bin/python
...

Olhando para /proc/<pid>/comm ou usando pgrep , parece que ...

... o nome do processo é "miragem" quando eu o chamo via shebang:

/usr/bin/mirage &

... mas é "python" quando eu chamo o python explicitamente:

/usr/bin/python /usr/bin/mirage &
  • Eu entendo que um processo pode mudar seu próprio nome, mas por que o nome não é o mesmo em ambos os casos?
  • Existe uma maneira genérica de saber como um processo foi originalmente lançado (usando apenas /proc ou grep information)?

Detalhes - shebang

/home/martin> /usr/bin/mirage &
[1] 22638

/ proc / < pid > / comm diz que é "miragem"

/home/martin> cat /proc/22638/comm 
mirage

pgrep encontra-o como "mirage" mas não como "python"

/home/martin> pgrep -al mirage && echo "found" || echo "not found"
22638 /usr/bin/python /usr/bin/mirage
found

/home/martin> pgrep -al python && echo "found" || echo "not found"
not found

Detalhes - python

/home/martin> /usr/bin/python /usr/bin/mirage &
[1] 21348

/ proc / < pid > / comm diz que é "python"

/home/martin> cat /proc/21348/comm 
python

pgrep encontra-o como "python", mas não como "miragem"

/home/martin> pgrep -al mirage && echo "found" || echo "not found"
not found

/home/martin> pgrep -al python && echo "found" || echo "not found"
21348 /usr/bin/python /usr/bin/mirage
found
    
por Martin Drautzburg 25.08.2018 / 14:24

2 respostas

1

I understand that a process can change its own name, but why isn't the name the same in both cases?

Porque os programas envolvidos não estão mudando seus próprios nomes. Eles recebem os nomes que o comportamento padrão do Linux atribui. (Outros sistemas operacionais se comportam de maneira diferente, mas essa é uma questão do Linux porque fala sobre /proc/*/comm arquivos.)

No Linux, o nome do programa em comm é obtido de qualquer nome do arquivo de imagem do programa passado para execve() . Note que este não é nem o vetor argumento nem o vetor ambiente, e a declaração de que este nome é retirado do vetor argumento no Linux é errônea.

Os nomes dos arquivos de imagem do programa que o shell está realmente passando são /usr/bin/python e /usr/bin/mirage , então python e mirage são para os quais /proc/self/comm foram inicializados. ( comm é o nome da base do nome do arquivo da imagem do programa, truncado / preenchido).

O vetor argumento inicializa o que um processo tem em /proc/self/cmdline e o vetor ambiente inicializa o que tem em /proc/self/environ . Então, com estes e /proc/self/comm , e presumindo que um programa não os altere quando executado, você conhece todas as três informações que foram passadas para execve() e, portanto, exatamente como um processo foi originalmente lançado (embora Estritamente falando, é assim que o programa foi lançado, pois o processo foi lançado com fork() ).

Aqui está um exemplo dessas três partes em ação, usando clearenv , setenv e exec do conjunto de ferramentas para configurar um ambiente pequeno e forçar argv[0] para fins de exposição:

% clearenv setenv 1THIS 'is the environment string' setenv 2COMPRISING 'all of the environment.' \
> exec -a 'This is argv[0].' /bin/sleep 100 &
[1] 15564
% for i in /proc/$\!/{comm,cmdline,environ} ; do printf "%s:" $i ; cat -v $i ; printf "\n" ; done
/proc/15564/comm:3

/proc/15564/cmdline:This is argv[0].^@100^@
/proc/15564/environ:1THIS=is the environment string^@2COMPRISING=all of the environment.^@
%

E, de fato, esses são exatamente o que o comando exec do conjunto de ferramentas de nos passou para execve() para executar /bin/sleep . (O 3 é porque exec usa a função fexecve() da biblioteca C, que usa internamente nomes de arquivos de imagens de programas no formato /proc/self/fd/3 .)

O arquivo de imagem do programa que passa a ser um script com um intérprete nomeado e o número mágico #! , causando a substituição desse interpretador pelo arquivo de imagem do programa e o deslocamento do vetor argumento, não muda o que entra em comm . Permanece como qualquer nome de arquivo de imagem do programa originalmente dado a execve() . Sim, o Linux é inconsistente aqui, porque faz alterar o que entra em cmdline em tais casos para ser a sequência de argumentos final efetiva.

Leitura adicional

  • link
  • link
  • link
  • link
  • Jonathan de Boyne Pollard (2018). " clearenv ". Manual . conjunto de ferramentas. Softwares.
  • Jonathan de Boyne Pollard (2018). " setenv ". Manual . conjunto de ferramentas. Softwares.
  • Jonathan de Boyne Pollard (2018). " exec ". Manual . conjunto de ferramentas. Softwares.
por 25.08.2018 / 21:51
2

O nome do processo é derivado de argv[0] na chamada execv() .

Isso explica o comportamento que você observa.

O fato de que no caso do shebang o kernel reorganiza como as coisas são chamadas não afeta o vetor argv .

    
por 25.08.2018 / 14:30