Często występuje pomieszanie między rozwidlaniem procesów a wykonywaniem.
Gdy zrobisz to z polecenia bash
powłoki.
$ sh -c 'exec env ps'
Proces P1 wydający ten $
monit aktualnie uruchamia bash
kod. Ten bash
kod powoduje uruchomienie nowego procesu P2 , /bin/sh
który następnie wykonuje się /usr/bin/env
, a następnie wykonuje /bin/ps
.
Więc P2 jest z kolei wykonany kod bash
, sh
, env
i ps
.
ps
(lub jakiekolwiek inne polecenie, takie jak skrypt, którego użylibyśmy tutaj zamiast tego) nie ma sposobu, aby wiedzieć, że zostało ono wykonane przez env
polecenie.
Wszystko, co może zrobić, to dowiedzieć się, jaki jest jego identyfikator procesu nadrzędnego, którym w tym przypadku byłby P1 lub 1
gdyby P1 zmarł w tym przedziale czasu, lub w systemie Linux inny proces, który został wyznaczony jako podrzędny zamiast 1
.
Następnie może zapytać system o to, jakie polecenie aktualnie wykonuje ten proces (jak readlink /proc/<pid>/exe
w systemie Linux) lub jakie argumenty zostały przekazane do ostatniego polecenia, które wykonał (jak w przypadku ps -o args= -p <pid>
).
Jeśli chcesz, aby skrypt wiedział, co go wywołało, niezawodnym sposobem byłoby, aby wywołujący go powiedział. Można to zrobić na przykład za pomocą zmiennej środowiskowej. Na przykład script1
można zapisać jako:
#! /bin/sh -
INVOKER=$0 script2 &
I 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
będzie ( ogólnie ) zawierać ścieżkę do script1
. W niektórych przypadkach może to być ścieżka względna, a ścieżka będzie względna do bieżącego katalogu roboczego w momencie script1
uruchomienia. Więc jeśli script1
zmieni bieżący katalog roboczy przed wywołaniem script2
, script2
otrzyma błędne informacje o tym, co go wywołało. Dlatego może być wskazane, aby upewnić się, że $INVOKER
zawiera ścieżkę bezwzględną (najlepiej zachowując basename), na przykład pisząc script1
jako:
#! /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
W powłokach POSIX $PPID
będzie zawierał pid rodzica procesu, który wykonał powłokę w momencie inicjalizacji tej powłoki. Następnie, jak pokazano powyżej, proces nadrzędny może ulec zmianie, jeśli proces id $PPID
umrze.
zsh
w zsh/system
module może zapytać o bieżący nadrzędny pid bieżącej (pod-) powłoki za pomocą $sysparams[ppid]
. W powłokach POSIX można uzyskać bieżący ppid procesu, który wykonał interpreter (zakładając, że nadal działa) ps -o ppid= -p "$$"
. Za pomocą bash
można uzyskać ppid bieżącej (pod-) powłoki za pomocą ps -o ppid= -p "$BASHPID"
.