No primeiro exemplo, o shell com PID 100648 é seu shell interativo, enquanto sleep é de fato o processo que substituiu bash -c '' process. O execve() syscall gera um novo programa que retém o PID do processo original que chamado, daí porque você não vê o original bash -c '' lá. A razão simples de porque os comandos simples substituem o processo shell é porque ele economiza recursos, conforme explicado na resposta de Stephane .
Isso também é evidente em um teste simples em um terminal:
$ echo $$
10250
$ bash -c 'sleep 60'
E em outro:
$ pstree -p 10250
bash(10250)───sleep(21031)
Por que isso acontece dessa forma, é porque há apenas um comando simples sem canos e bash executa execve direta para comandos simples .
Exatamente por esse motivo, bash reconhece que você tem várias instruções de comando no segundo exemplo, portanto, para cada comando sleep que você tem em "sleep 10000; sleep 99999 " . No primeiro caso, execve() pode apenas substituir o processo pai e quando as novas saídas - não há problema. Mas aqui o shell não pode sair após o primeiro comando ser concluído. Portanto, haverá fork e execve para sleep 10000 , que é o que você vê na saída de pstree e, posteriormente, um novo fork e execve para sleep 99999
Outro teste que você pode realizar para acreditar que o comando simples em bash -c '' substitui o processo shell é este:
$ bash -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
/proc/self/status:Pid: 23946
/proc/23946/status:Pid: 23946
Note que esse comportamento é específico do bash. Para /bin/dash em distros baseadas no Debian (e também evidente em strace , também):
$ sh -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
/proc/self/status:Pid: 24188
/proc/24187/status:Pid: 24187