Ich starte einen Hintergrundprozess von meinem Shell-Skript aus und möchte diesen Prozess abbrechen, 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.
Sie müssen die PID des Hintergrundprozesses beim Start speichern:
foo &
FOO_PID=$!
# do other stuff
kill $FOO_PID
Sie können die Auftragssteuerung nicht verwenden, da dies eine interaktive Funktion ist, die an ein steuerndes Terminal gebunden ist. Da an ein Skript nicht unbedingt ein Terminal angehängt sein muss, ist die Auftragssteuerung nicht unbedingt verfügbar.
Du kannst den ... benutzen jobs -l
Befehl, um zu einem bestimmten Job zu gelangen
^Z
[1]+ Stopped guard
my_mac:workspace r$ jobs -l
[1]+ 46841 Suspended: 18 guard
In diesem Fall ist 46841 die PID.
Von help jobs
:
-l Zeigt die Prozessgruppen-ID und das Arbeitsverzeichnis der Jobs an.
jobs -p
ist eine weitere Option, die nur die PIDs anzeigt.
$$
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 aus jobs
):
$ echo $$
3748
$ sleep 100 &
[1] 192
$ echo $!
192
$ kill %1
[1]+ Terminated sleep 100
Eine noch einfachere Möglichkeit, alle untergeordneten Prozesse eines Bash-Skripts zu beenden:
pkill -P $$
Das -P
flag funktioniert genauso mit pkill
und pgrep
- es werden untergeordnete Prozesse abgerufen, nur mit pkill
werden die untergeordneten Prozesse beendet und mit pgrep
untergeordneten PIDs werden nach Standard gedruckt.
das habe ich getan Probieren Sie es aus, ich hoffe, es kann helfen.
#!/bin/bash
#
# So something to show.
echo "UNO" > UNO.txt
echo "DOS" > DOS.txt
#
# Initialize Pid List
dPidLst=""
#
# Generate background processes
tail -f UNO.txt&
dPidLst="$dPidLst $!"
tail -f DOS.txt&
dPidLst="$dPidLst $!"
#
# Report process IDs
echo PID=$$
echo dPidLst=$dPidLst
#
# Show process on current Shell
ps -f
#
# Start killing background processes from list
for dPid in $dPidLst
do
echo killing $dPid. Process is still there.
ps | grep $dPid
kill $dPid
ps | grep $dPid
echo Just ran "'"ps"'" command, $dPid must not show again.
done
Dann starte es einfach als: ./bgkill.sh
mit den richtigen Berechtigungen natürlich
[email protected] [P]:~# ./bgkill.sh
PID=23757
dPidLst= 23758 23759
UNO
DOS
UID PID PPID C STIME TTY TIME CMD
root 3937 3935 0 11:07 pts/5 00:00:00 -bash
root 23757 3937 0 11:55 pts/5 00:00:00 /bin/bash ./bgkill.sh
root 23758 23757 0 11:55 pts/5 00:00:00 tail -f UNO.txt
root 23759 23757 0 11:55 pts/5 00:00:00 tail -f DOS.txt
root 23760 23757 0 11:55 pts/5 00:00:00 ps -f
killing 23758. Process is still there.
23758 pts/5 00:00:00 tail
./bgkill.sh: line 24: 23758 Terminated tail -f UNO.txt
Just ran 'ps' command, 23758 must not show again.
killing 23759. Process is still there.
23759 pts/5 00:00:00 tail
./bgkill.sh: line 24: 23759 Terminated tail -f DOS.txt
Just ran 'ps' command, 23759 must not show again.
[email protected] [P]:~# ps -f
UID PID PPID C STIME TTY TIME CMD
root 3937 3935 0 11:07 pts/5 00:00:00 -bash
root 24200 3937 0 11:56 pts/5 00:00:00 ps -f
Möglicherweise können Sie auch pstree verwenden:
pstree -p user
Dies gibt normalerweise eine Textdarstellung aller Prozesse für den "Benutzer" und die Option -p gibt die Prozess-ID an. Soweit ich weiß, kommt es nicht darauf an, dass die Prozesse der aktuellen Shell gehören. Es zeigt auch Gabeln.
Mit pgrep
können Sie alle untergeordneten PIDs eines übergeordneten Prozesses abrufen. Wie bereits erwähnt $$
ist die aktuelle PID des Skripts. Wenn Sie also ein Skript wünschen, das nach sich selbst aufräumt, sollte dies der Trick sein:
trap 'kill $( pgrep -P $$ | tr "\n" " " )' SIGINT SIGTERM EXIT