Muitas vezes há confusão entre o processo de bifurcação e execução.
Quando você faz no prompt de um shell bash
.
$ sh -c 'exec env ps'
O processo P1 emitindo esse prompt $
está atualmente executando bash
code. Esse código bash
bifurca um novo processo P2 que executa /bin/sh
, que então executa /usr/bin/env
, que então executa /bin/ps
.
Portanto, o P2 executou o código de bash
, sh
, env
e ps
.
ps
(ou qualquer outro comando como um script que usaríamos aqui) não tem como saber que ele foi executado pelo comando env
.
Tudo o que ele pode fazer é descobrir qual é o ID do processo pai, que nesse caso seria P1 ou 1
se P1 tiver morrido no intervalo ou no Linux outro processo que foi designado como um sub subinterrupto em vez de 1
.
Ele pode então consultar o sistema sobre qual comando esse processo está atualmente em execução (como com readlink /proc/<pid>/exe
no Linux) ou quais argumentos foram passados para o último comando executado (como com ps -o args= -p <pid>
).
Se você quiser que seu script saiba o que o invocou, uma maneira confiável seria fazer com que o invocador o contasse. Isso pode ser feito, por exemplo, através de uma variável de ambiente. Por exemplo, script1
pode ser escrito como:
#! /bin/sh -
INVOKER=$0 script2 &
e script2
:
#! /bin/sh -
printf '%s\n' "I was invoked by $INVOKER"
# and in this case, we'll probably find the parent process is 1
# (if not now, at least one second later) as script1 exited just after
# invoking script2:
ps -fp "$$"
sleep 1
ps -fp "$$"
exit
$INVOKER
will ( geralmente ) contém um caminho para script1
. Em alguns casos, pode ser um caminho relativo e o caminho será relativo ao diretório de trabalho atual no momento em que script1
iniciou. Portanto, se script1
alterar o diretório de trabalho atual antes de chamar script2
, script2
obterá informações erradas sobre o que chamou. Por isso, pode ser preferível certificar-se de que $INVOKER
contenha um caminho absoluto (preferivelmente mantendo o nome da base), como escrevendo script1
as:
#! /bin/sh -
mypath=$(
mydir=$(dirname -- "$0") &&
cd -P -- "$mydir" &&
pwd -P) && mypath=$mypath/$(basename -- "$0") || mypath=$0
... some code possibly changing the current working directory
INVOKER=$mypath script2
Em shells POSIX, $PPID
conterá o pid do pai do processo que executou o shell no momento da inicialização do shell. Depois disso, como visto acima, o processo pai pode mudar se o processo de id $PPID
morrer.
zsh
no módulo zsh/system
, pode consultar o pid pai atual do (sub) shell atual com $sysparams[ppid]
. Em shells POSIX, você pode obter o atual ppid do processo que executou o interpretador (assumindo que ele ainda está em execução) com ps -o ppid= -p "$$"
. Com bash
, você pode obter o ppid da (sub) shell atual com ps -o ppid= -p "$BASHPID"
.