Diferença entre bg e kill -CONT

1

Eu estava rodando um aplicativo em primeiro plano e coloquei em segundo plano pressionando CTRL + Z (e parou). Para recuperá-lo, executei o comando bg %1 (que é o seu JOBSPEC).

Pensei por que não tentar recuperá-lo com kill -CONT <PID> . Então, eu corri jobs -l para obter seu PID, e usei esse pid com kill com sinal CONT.

No entanto, o programa não foi ativado novamente! jobs -l depois de tentar matar com relatórios CONT que está sendo executado, mas não está (como está esmaecido).

Eu olhei os aplicativos PID usando o comando ps e encontrei dois do mesmo comando com PIDs diferentes (e status Tl ).

Em seguida, olhei a mesma coisa usando pstree e descobri que estão todos em processo pai. O processo pai é diferente daquele listado por jobs -l , pois parece que o que eu coloquei em segundo plano iniciou outro programa. O outro programa parece ter criado processos filhos.

O que eu notei é resumido como:

  • Usar kill para enviar CONT para o processo pai faz com que o programa seja executado.

  • O PID do processo pai é diferente do relatado por jobs -l . Em outras palavras, o processo para o qual eu deveria ter enviado o sinal CONT é diferente daquele que eu usei usando jobs -l .

  • O envio de CONT para um processo pai não aplica o mesmo sinal nos filhos.

  • Usando o comando bg para retornar um processo para execução, envia o sinal CONT para o pai a todos os seus filhos.

As minhas conclusões estão corretas? Em caso afirmativo, isso significa usar o comando bg para economizar tempo de envio do CONT para todos os processos relacionados. Isso está correto?

EDIT O aplicativo principal que eu chamei da linha de comando e que eu coloquei em segundo plano é git difftool . O outro aplicativo que eu estou falando que criou novos filhos em si é meld que eu configurei para ser usado como a ferramenta de comparação no git.

    
por joker 26.09.2018 / 15:33

2 respostas

5

Em primeiro lugar, jobs -l não lista processos, mas processam grupos (também conhecidos como jobs). Cada grupo de processos tem um líder de processo, cujo ID de processo (pid) é igual ao seu id de grupo de processos (pgid).

Para enviar um sinal a todos os processos em um grupo de processos, e não apenas ao seu líder, você deve chamar kill com o negativo do pgid. Isso é descrito na manpage kill (2):

If pid is less than -1, then sig is sent to every process in the process group whose ID is -pid.

O mesmo funciona no shell:

$ sh -c 'while echo -n 1; do sleep 1; done'
111^Z
[1]+  Stopped                 sh -c 'while echo -n 1; do sleep 1; done'
$ jobs -l
[1]+ 11046 Stopped                 sh -c 'while echo -n 1; do sleep 1; done'
$ kill -CONT 11046
   <nothing>
$ kill -CONT -11046
$ 11111111...

Agora, para suas conclusões:

Using kill to send CONT to the parent process gets the program running.

correto

The parent process PID is different from the one reported by jobs -l. In other words, the process I should have sent CONT signal to is different from the one I find using jobs -l.

errado, é o mesmo pid, e também é igual ao pgid.

Sending CONT to a parent process doesn't apply the same signal on the children.

correto

Using the command bg to return a process to running, sends CONT signal to the parent and all its children.

correto, mas somente se o pai e os filhos estiverem todos no mesmo grupo de processos. Além disso, ele não chama kill (2) para cada processo, basta chamá-lo uma vez com o negativo do pgid (= pid do líder do grupo de processos) e conta com o kernel para rotear o sinal para todos os processos. nesse grupo.

    
por 27.09.2018 / 02:12
0

Eu não vejo esse comportamento aqui.

  • Aqui está o meu código de exemplo, inserido na íntegra na linha de comando:

    bash -c 'echo This is parent $$; sleep 7; bash -c "echo This is child \$$; sleep 7; echo Child done"; echo This is parent $$ again; sleep 7'
    
  • Assim que você obtiver a mensagem This is child xx , pressione Ctrl Z para suspender o processo.

  • Aguarde mais 7 segundos para confirmar que realmente pausou

  • Agora, jobs -l para listar o líder do processo (pai PID). Na verdade, podemos usar o número de jobs, neste caso %1

  • Continue o processo no plano de fundo kill -CONT %1

Eu vi que a criança continuou e depois saiu, permitindo que os pais completassem.

Aqui está o resultado da execução completa (incluindo >$ shell prompts)

>$ bash -c 'echo This is parent $$; sleep 7; bash -c "echo This is child \$$; sleep 7; echo Child done"; echo This is parent $$ again; sleep 7'
This is parent 2004
This is child 10696

[1]+  Stopped                 bash -c 'echo This is parent $$; sleep 7; bash -c "echo This is child \$$; sleep 7; echo Child done"; echo This is parent $$ again; sleep 7'
>$ jobs -l
[1]+  2004 Stopped                 bash -c 'echo This is parent $$; sleep 7; bash -c "echo This is child \$$; sleep 7; echo Child done"; echo This is parent $$ again; sleep 7'
>$ kill -CONT %1
>$ Child done
This is parent 2004 again

Se você quiser experimentar mais com um arnês de teste automatizado, você pode usar kill -TSTP ... para enviar o mesmo sinal que é gerado por Ctrl Z no teclado .

    
por 26.09.2018 / 16:38