Es gibt oft eine Verwechslung zwischen Prozess-Forking und Ausführung.
Wenn Sie an der Eingabeaufforderung einer bash
Shell tun .
$ sh -c 'exec env ps'
Der Prozess P1 , der diese $
Eingabeaufforderung ausgibt, führt derzeit bash
Code aus. Dieser bash
Code gibt einen neuen Prozess P2 aus , der ausgeführt wird, /bin/sh
der dann ausgeführt wird /usr/bin/env
und der dann ausgeführt wird/bin/ps
.
So P2 wiederum hat Code ausgeführt bash
, sh
, env
und ps
.
ps
(oder ein anderer Befehl wie ein Skript, den wir stattdessen hier verwenden würden) kann nicht wissen, dass er vom env
Befehl ausgeführt wurde .
Alles, was es tun kann, ist herauszufinden, wie die übergeordnete Prozess-ID lautet. In diesem Fall ist dies entweder P1, oder 1
wenn P1 im Intervall abgestorben ist, oder unter Linux ein anderer Prozess, der stattdessen als Subreaper festgelegt wurde1
.
Anschließend kann das System abgefragt werden, welcher Befehl von diesem Prozess gerade ausgeführt wird (wie bei readlink /proc/<pid>/exe
Linux) oder welche Argumente an den zuletzt ausgeführten Befehl übergeben wurden (wie bei Linux)ps -o args= -p <pid>
).
Wenn Sie möchten, dass Ihr Skript weiß, was es aufgerufen hat, können Sie es auf zuverlässige Weise vom Aufrufer mitteilen lassen. Dies kann beispielsweise über eine Umgebungsvariable erfolgen. Zum Beispiel script1
könnte geschrieben werden als:
#! /bin/sh -
INVOKER=$0 script2 &
Und 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
wird ( allgemein ) einen Pfad zu enthalten script1
. In einigen Fällen kann es sich jedoch um einen relativen Pfad handeln, der sich auf das aktuelle Arbeitsverzeichnis zum Zeitpunkt des script1
Starts bezieht. Wenn Sie also script1
das aktuelle Arbeitsverzeichnis vor dem Aufruf ändern script2
, script2
erhalten Sie falsche Informationen darüber, wie es aufgerufen wurde. Es kann daher vorzuziehen sein, sicherzustellen, dass $INVOKER
ein absoluter Pfad enthalten ist (vorzugsweise unter Beibehaltung des Basisnamens), indem Sie wie folgt schreiben 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
Enthält in POSIX-Shells $PPID
die PID des übergeordneten Prozesses, der die Shell zum Zeitpunkt der Shell-Initialisierung ausgeführt hat. Danach kann sich, wie oben gezeigt, der übergeordnete Prozess ändern, wenn der Prozess von id $PPID
stirbt.
zsh
Im zsh/system
Modul kann mit die aktuelle Eltern-PID der aktuellen (Sub-) Shell abgefragt werden $sysparams[ppid]
. In POSIX-Shells können Sie die aktuelle ppid des Prozesses abrufen, mit dem der Interpreter ausgeführt wurde (sofern er noch ausgeführt wird) ps -o ppid= -p "$$"
. Mit bash
können Sie die ppid der aktuellen (Sub-) Shell mit erhalten ps -o ppid= -p "$BASHPID"
.