Por que $$ está retornando o mesmo ID do processo pai?

159

Estou com um problema com o Bash e não sei por que.
Sob shell, insiro:

echo $$    ## print 2433
(echo $$)  ## also print 2433
(./getpid) ## print 2602

"getpid" é um programa em C para obter o pid atual, como:

   int main() {
    printf("%d", (int)getpid());
    return 0;
   }

O que me confunde é o seguinte:

  1. Eu acho que "(comando)" é um subprocesso (estou certo?), E acho que seu pid deve ser diferente do pid pai, mas são os mesmos, por que ...
  2. Quando eu uso meu programa para mostrar pid entre parênteses, o pid mostra é diferente, está certo?
  3. '$$' é algo como macro?

Pode me ajudar?

ruanhao
fonte
8
Observe que getpidmostraria um ID de processo diferente, mesmo que não fosse executado em um subshell.
chepner
1
@Marian echo $$ $BASHPID ; ( echo $$ $BASHPID )demonstra que sim. Parênteses arredondados criam um subshell. As instruções podem alterar os valores das variáveis ​​e o shell pai não deve ver essas alterações. Isso é implementado como uma fork()operação.
Ben

Respostas:

222

$$é definido para retornar o ID do processo do pai em um subshell; na página do manual em "Parâmetros especiais":

$ Expande para o ID do processo do shell. Em um subshell (), ele expande para o ID do processo do shell atual, não para o subshell.

Em bash4, você pode obter o ID do processo da criança BASHPID.

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634
chepner
fonte
16
"pai" é um pouco enganador (pelo menos para mim), na verdade é o shell de "nível superior". Por exemplo: echo $$; (echo $$; (echo $$))ecoa o mesmo pid três vezes
Martin Bouladour
1
Certo; Eu deveria ter dito que o valor é herdada de um shell pai (que herdou seu valor a partir de seu pai, etc). O shell de nível superior o define inicialmente, em vez de herdar do processo pai (sem shell).
chepner
$ Expands to the process ID of the shellisso tho? echo $apenas ecoa o literal $.
Alexander Mills
@AlexanderMills Bem, sim; $sozinho não é uma expansão de parâmetro. A página de manual está se referindo ao nome do parâmetro especial, que é $; não está afirmando que $só se expande.
Chepner 31/05/19
Ok eu honestamente não tenho idéia do que isso significa, mas echo $BASHPIDobras em festa de 4 e 5 (mas não a versão 3.2.57 em MacOS)
Alexander Mills
81

Você pode usar um dos seguintes.

  • $! é o PID do último processo em segundo plano.
  • kill -0 $PID verifica se ainda está em execução.
  • $$ é o PID do shell atual.
enlouquecer
fonte
2
A segunda bala não deveria ser kill -0 $!se estamos falando de processos em segundo plano? PIDnão está definido para nada por padrão.
Isaac Freeman
26
  1. Parênteses invocam um subshell no Bash . Como é apenas um subshell, ele pode ter o mesmo PID - depende da implementação.
  2. O programa C que você chama é um processo separado, que possui seu próprio PID exclusivo - não importa se está em um subshell ou não.
  3. $$é um alias no Bash para o script atual PID . Veja as diferenças entre $$e $BASHPIDaqui , e logo acima da variável adicional $BASH_SUBSHELLque contém o nível de aninhamento.
Niels Keurentjes
fonte
4

Tente getppid()se você deseja que seu programa C imprima o PID do seu shell.

Alex
fonte
2

Se você estava perguntando como obter o PID de um comando conhecido, ele se pareceria com algo assim:

Se você emitiu o comando abaixo #O comando emitido foi ***

dd se = / dev / diskx de = / dev / disky


Então você usaria:

PIDs=$(ps | grep dd | grep if | cut -b 1-5)

O que acontece aqui é canalizar todos os caracteres exclusivos necessários para um campo e esse campo pode ser repetido usando

echo $ PIDs

Don-Pierre Halfaway
fonte
1

esta maneira univesal de obter pid correto

pid=$(cut -d' ' -f4 < /proc/self/stat)

mesmo bom trabalhou para sub

SUB(){
    pid=$(cut -d' ' -f4 < /proc/self/stat)
    echo "$$ != $pid"
}

echo "pid = $$"

(SUB)

verificar saída

pid = 8099
8099 != 8100
ARTEM LAPKIN
fonte
Boa ideia, mas isso não vai te dar o pid do garfo que a concha executou para capturar a saída do corte? Se eu executá-lo duas vezes, uma vez com echo $ (...) e uma vez sem, então recebo respostas diferentes.
Martin Dorey