Ich starte einen Hintergrundprozess von meinem Shell-Skript aus und möchte diesen Prozess beenden, wenn mein Skript beendet ist.
Wie erhalte ich die PID dieses Prozesses aus meinem Shell-Skript? Soweit ich sehen kann, $!
enthält die Variable die PID des aktuellen Skripts, nicht den Hintergrundprozess.
linux
shell
background-process
pid
Volodymyr Bezuglyy
quelle
quelle
Antworten:
Sie müssen die PID des Hintergrundprozesses zum Zeitpunkt des Starts speichern:
Sie können die Jobsteuerung nicht verwenden, da dies eine interaktive Funktion ist und an ein steuerndes Terminal gebunden ist. An ein Skript muss nicht unbedingt ein Terminal angeschlossen sein, sodass die Jobsteuerung nicht unbedingt verfügbar ist.
quelle
foo
und beginnt$!
und wir bekommen, dass etwas pid stattfoo
's ist?foo
es sich um Befehle mit mehreren Leitungen handelt (z. B.tail -f somefile.txt | grep sometext
). In solchen Fällen erhalten Sie die PID des Befehls grep$!
anstelle des Befehls tail, wenn Sie danach gesucht haben. In diesem Fall müssen Siejobs
oderps
oder ähnliche verwenden.grep
, aber wenn Sie das töten, bekommt der Schwanz ein ZEICHEN, wenn er versucht, in die Pipe zu schreiben. Sobald Sie jedoch versuchen, in eine schwierige Prozessverwaltung / -steuerung einzusteigen, wird Bash / Shell ziemlich schmerzhaft./bin/sh -c 'echo $$>/tmp/my.pid && exec program args' &
- Sysfault 24. November 10 um 14:28Mit dem
jobs -l
Befehl können Sie zu einem bestimmten Job gelangenIn diesem Fall ist 46841 die PID.
Von
help jobs
:jobs -p
ist eine weitere Option, die nur die PIDs anzeigt.quelle
$!
unmittelbar nach dem Start ist in den meisten Situationen portabler und unkomplizierter. Das macht die aktuell akzeptierte Antwort.jobs -p
kehrte das gleiche zurück wiejobs -l
auf Lubuntu 16.4$$
ist die PID des aktuellen Skripts$!
ist die PID des letzten HintergrundprozessesHier ist ein Beispielprotokoll einer Bash-Sitzung (
%1
bezieht sich auf die Ordnungszahl des Hintergrundprozesses, wie aus ersichtlichjobs
):quelle
%1
Rückkehr auf meinem Ubuntu den Hintergrundprozess nicht währendecho $!
tutEine noch einfachere Möglichkeit, den gesamten untergeordneten Prozess eines Bash-Skripts zu beenden:
Das
-P
Flag funktioniert genauso mitpkill
undpgrep
- es erhält untergeordnete Prozesse, nur wenn die untergeordnetenpkill
Prozesse beendet werden und mitpgrep
untergeordneten PIDs auf stdout gedruckt werden.quelle
bash -c 'bash -c "sleep 300 &"' &
Laufenpgrep -P $$
wird nichts angezeigt, da der Schlaf kein direktes Kind Ihrer Muschel ist.$$
bezieht sich auf die aktuelle Shell.bash -c 'bash -c "sleep 300 &"' & ; pgrep -P $$
, ich komme auf stdout[1] <pid>. So at least it shows something, but this is probably not the output of
pgrep`bash -c 'bash -c "sleep 10 & wait $!"' & sleep 0.1; pstree -p $$
das habe ich getan Probieren Sie es aus, hoffe es kann helfen.
Dann führen Sie es einfach aus als:
./bgkill.sh
natürlich mit den richtigen Berechtigungenquelle
Möglicherweise können Sie auch pstree verwenden:
Dies gibt normalerweise eine Textdarstellung aller Prozesse für den "Benutzer" und die Option -p gibt die Prozess-ID an. Soweit ich weiß, hängt es nicht davon ab, ob die Prozesse der aktuellen Shell gehören. Es zeigt auch Gabeln.
quelle
pgrep
Sie können alle untergeordneten PIDs eines übergeordneten Prozesses abrufen. Wie bereits erwähnt,$$
ist die aktuelle Skript-PID. Wenn Sie also ein Skript möchten, das nach sich selbst bereinigt, sollte dies den Trick tun:quelle
trap 'pkill -P $$' SIGING SIGTERM EXIT
sieht einfacher aus, aber ich habe es nicht getestet.SIG
Präfix. Es ist von POSIX zulässig, jedoch nur als Erweiterung, die Implementierungen möglicherweise unterstützen: pubs.opengroup.org/onlinepubs/007904975/utilities/trap.html Die Dash-Shell beispielsweise nicht.