Gibt es in * nix world eine Möglichkeit für Shell-Skripte, Informationen darüber zu erhalten, welches Programm es ausgeführt hat?
Beispiel:
/path/to/script1 /path/to/script_xyz
in diesem imaginären Szenario script_xyz
hätte Pfadinformationen ( /path/to/script1
)
oder
PID verarbeiten
der Einheit, die es ausgeführt haben.
Hinweis: Ich bin neugierig auf verschiedene Lösungen und Ansätze und erwarte nicht, dass genau dies tatsächlich möglich ist
shell-script
shell
process
debugging
Miloš Đakonović
quelle
quelle
Antworten:
Es gibt oft eine Verwechslung zwischen Prozess-Forking und Ausführung.
Wenn Sie an der Eingabeaufforderung einer
bash
Shell tun .Der Prozess P1 , der diese
$
Eingabeaufforderung ausgibt, führt derzeitbash
Code aus. Dieserbash
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
undps
.ps
(oder ein anderer Befehl wie ein Skript, den wir stattdessen hier verwenden würden) kann nicht wissen, dass er vomenv
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:Und
script2
:$INVOKER
wird ( allgemein ) einen Pfad zu enthaltenscript1
. In einigen Fällen kann es sich jedoch um einen relativen Pfad handeln, der sich auf das aktuelle Arbeitsverzeichnis zum Zeitpunkt desscript1
Starts bezieht. Wenn Sie alsoscript1
das aktuelle Arbeitsverzeichnis vor dem Aufruf ändernscript2
,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 schreibenscript1
: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
Imzsh/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 "$$"
. Mitbash
können Sie die ppid der aktuellen (Sub-) Shell mit erhaltenps -o ppid= -p "$BASHPID"
.quelle
Ja, ein Programm kann wissen, wer sein Elternteil ist.
Zur Veranschaulichung erstellen wir zwei Bash-Skripte. Der erste meldet seine PID und startet das zweite Skript:
Das zweite Skript gibt die Prozess-ID, die PID des übergeordneten Skripts und die zum Ausführen des übergeordneten Skripts verwendete Befehlszeile an:
Jetzt lass es uns laufen:
Wie Sie sehen, kennt das zweite Skript die PID seines übergeordneten Skripts. Unter Verwendung
ps
dieser PID wird die Befehlszeile angezeigt, die zum Aufrufen des übergeordneten Elements verwendet wird.Weitere Informationen zu PPID finden Sie in der Antwort von Stéphane Chazelas .
quelle
s1
,s2
undPPID
Werte , aber dann, in mehreren Linien nachERROR: Unsupported SysV option.
und mehrere Zeilen mit zusätzlichen Erläuterungen und - leeren Wert fürParent command
ps
demprocps-ng
Paket, Version 3.3.12, getestet. Wie Jasen vorgeschlagen hat, verwenden Sie wahrscheinlich eine andere Version, für die möglicherweise eine andere Syntax zum Drucken der Befehlszeile des übergeordneten Elements erforderlich ist. Versuchen Sie esps -f | grep $PPID
.