Il y a souvent une confusion entre le forking de processus et l'exécution.
Lorsque vous le faites à l'invite d'un bash
shell.
$ sh -c 'exec env ps'
Le processus P1 émettant cette $
invite exécute actuellement du bash
code. Ce bash
code crée un nouveau processus P2 qui s'exécute /bin/sh
puis s'exécute /usr/bin/env
, qui s'exécute ensuite /bin/ps
.
Alors P2 a à son tour exécuté code bash
, sh
, env
et ps
.
ps
(ou toute autre commande comme un script que nous utiliserions à la place ici) n'a aucun moyen de savoir qu'il a été exécuté par la env
commande.
Tout ce qu'il peut faire est de découvrir quel est son identifiant de processus parent, qui dans ce cas serait P1 ou 1
si P1 est mort dans l'intervalle ou sous Linux un autre processus qui a été désigné comme sous- segment à la place de 1
.
Il peut alors interroger le système pour savoir quelle commande ce processus est en cours d' exécution (comme avec readlink /proc/<pid>/exe
Linux) ou quels arguments ont été passés à la dernière commande qu'il a exécutée (comme avec ps -o args= -p <pid>
).
Si vous voulez que votre script sache ce qui l'a invoqué, un moyen fiable serait de le faire dire à l'invocateur. Cela pourrait être fait par exemple via une variable d'environnement. Par exemple, script1
pourrait s'écrire:
#! /bin/sh -
INVOKER=$0 script2 &
Et 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
contiendra ( généralement ) un chemin vers script1
. Dans certains cas, il peut cependant s'agir d'un chemin relatif et le chemin sera relatif au répertoire de travail en cours au moment du script1
démarrage. Donc, si vous script1
changez le répertoire de travail actuel avant d'appeler script2
, script2
vous obtiendrez des informations erronées sur ce qui l'a appelé. Il peut donc être préférable de s'assurer qu'il $INVOKER
contient un chemin absolu (de préférence en gardant le nom de base) comme en écrivant script1
:
#! /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
Dans les shells POSIX, $PPID
contiendra le pid du parent du processus qui a exécuté le shell au moment de son initialisation. Après cela, comme vu ci-dessus, le processus parent peut changer si le processus d'ID $PPID
meurt.
zsh
dans le zsh/system
module, peut interroger le courant pid parent de l'enveloppe de courant (sous-) avec $sysparams[ppid]
. Dans les shells POSIX, vous pouvez obtenir le ppid actuel du processus qui a exécuté l'interpréteur (en supposant qu'il est toujours en cours d'exécution) avec ps -o ppid= -p "$$"
. Avec bash
, vous pouvez obtenir le ppid du (sous-) shell actuel avec ps -o ppid= -p "$BASHPID"
.