GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Was ist der beste Weg, um ein Signal an alle Mitglieder einer Prozessgruppe zu senden?

Sie sagen nicht, ob der Baum, den Sie töten möchten, eine einzelne Prozessgruppe ist. (Dies ist häufig der Fall, wenn der Baum das Ergebnis einer Verzweigung von einem Serverstart oder einer Shell-Befehlszeile ist.) Sie können Prozessgruppen mit GNU ps wie folgt entdecken:

 ps x -o  "%p %r %y %x %c "

Wenn Sie eine Prozessgruppe beenden möchten, verwenden Sie einfach den kill(1) Befehl, aber anstatt ihm eine Prozessnummer zu geben, geben Sie ihm die Negation der Gruppennummer. Um beispielsweise jeden Prozess in Gruppe 5112 zu beenden, verwenden Sie kill -TERM -- -5112 .


Beenden Sie alle Prozesse, die zum selben Prozessbaum gehören unter Verwendung der Prozessgruppen-ID (PGID )

  • kill -- -$PGID Standardsignal verwenden (TERM =15)
  • kill -9 -$PGID Verwenden Sie das Signal KILL (9)

Sie können den PGID abrufen von einer beliebigen Prozess-ID (PID ) desselben Prozessbaums

  • kill -- -$(ps -o pgid= $PID | grep -o '[0-9]*') (Signal TERM )
  • kill -9 -$(ps -o pgid= $PID | grep -o '[0-9]*') (Signal KILL )

Erklärung

  • kill -9 -"$PGID" => Signal 9 senden (KILL ) an alle Kinder und Enkelkinder...
  • PGID=$(ps opgid= "$PID") => Rufen Sie die Prozessgruppen-ID ab von einer beliebigen Prozess-ID des Baums, nicht nur die Process-Parent-ID . Eine Variation von ps opgid= $PID ist ps -o pgid --no-headers $PID wobei pgid kann durch pgrp ersetzt werden .
    Aber:
    • ps fügt führende Leerzeichen ein, wenn PID ist weniger als fünf Ziffern und rechtsbündig, wie von Tanager bemerkt. Sie können Folgendes verwenden:
      PGID=$(ps opgid= "$PID" | tr -d ' ')
    • ps von OSX immer den Header drucken, daher schlägt Speakus vor:
      PGID="$( ps -o pgid "$PID" | grep [0-9] | tr -d ' ' )"
  • grep -o [0-9]* druckt nur aufeinanderfolgende Ziffern (druckt keine Leerzeichen oder alphabetischen Überschriften).

Weitere Befehlszeilen

PGID=$(ps -o pgid= $PID | grep -o [0-9]*)
kill -TERM -"$PGID"  # kill -15
kill -INT  -"$PGID"  # correspond to [CRTL+C] from keyboard
kill -QUIT -"$PGID"  # correspond to [CRTL+\] from keyboard
kill -CONT -"$PGID"  # restart a stopped process (above signals do not kill it)
sleep 2              # wait terminate process (more time if required)
kill -KILL -"$PGID"  # kill -9 if it does not intercept signals (or buggy)

Einschränkung

  • Wie von Davide und Hubert Kario bemerkt, als kill wird von einem Prozess aufgerufen, der zu demselben Baum gehört, kill riskiert, sich selbst zu töten, bevor das Töten des gesamten Baums beendet wird.
  • Achten Sie daher darauf, den Befehl mit einem Prozess auszuführen, der eine andere Prozessgruppen-ID hat .

Lange Geschichte

> cat run-many-processes.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
./child.sh background &
./child.sh foreground
echo "ProcessID=$$ ends ($0)"

> cat child.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
./grandchild.sh background &
./grandchild.sh foreground
echo "ProcessID=$$ ends ($0)"

> cat grandchild.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
sleep 9999
echo "ProcessID=$$ ends ($0)"

Führen Sie den Prozessbaum mit '&'

im Hintergrund aus
> ./run-many-processes.sh &    
ProcessID=28957 begins (./run-many-processes.sh)
ProcessID=28959 begins (./child.sh)
ProcessID=28958 begins (./child.sh)
ProcessID=28960 begins (./grandchild.sh)
ProcessID=28961 begins (./grandchild.sh)
ProcessID=28962 begins (./grandchild.sh)
ProcessID=28963 begins (./grandchild.sh)

> PID=$!                    # get the Parent Process ID
> PGID=$(ps opgid= "$PID")  # get the Process Group ID

> ps fj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
28348 28349 28349 28349 pts/3    28969 Ss   33021   0:00 -bash
28349 28957 28957 28349 pts/3    28969 S    33021   0:00  \_ /bin/sh ./run-many-processes.sh
28957 28958 28957 28349 pts/3    28969 S    33021   0:00  |   \_ /bin/sh ./child.sh background
28958 28961 28957 28349 pts/3    28969 S    33021   0:00  |   |   \_ /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3    28969 S    33021   0:00  |   |   |   \_ sleep 9999
28958 28963 28957 28349 pts/3    28969 S    33021   0:00  |   |   \_ /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3    28969 S    33021   0:00  |   |       \_ sleep 9999
28957 28959 28957 28349 pts/3    28969 S    33021   0:00  |   \_ /bin/sh ./child.sh foreground
28959 28960 28957 28349 pts/3    28969 S    33021   0:00  |       \_ /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3    28969 S    33021   0:00  |       |   \_ sleep 9999
28959 28962 28957 28349 pts/3    28969 S    33021   0:00  |       \_ /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3    28969 S    33021   0:00  |           \_ sleep 9999
28349 28969 28969 28349 pts/3    28969 R+   33021   0:00  \_ ps fj

Der Befehl pkill -P $PID tötet das Enkelkind nicht:

> pkill -P "$PID"
./run-many-processes.sh: line 4: 28958 Terminated              ./child.sh background
./run-many-processes.sh: line 4: 28959 Terminated              ./child.sh foreground
ProcessID=28957 ends (./run-many-processes.sh)
[1]+  Done                    ./run-many-processes.sh

> ps fj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
28348 28349 28349 28349 pts/3    28987 Ss   33021   0:00 -bash
28349 28987 28987 28349 pts/3    28987 R+   33021   0:00  \_ ps fj
    1 28963 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999
    1 28962 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999
    1 28961 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999
    1 28960 28957 28349 pts/3    28987 S    33021   0:00 /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3    28987 S    33021   0:00  \_ sleep 9999

Der Befehl kill -- -$PGID beendet alle Prozesse einschließlich des Enkels.

> kill --    -"$PGID"  # default signal is TERM (kill -15)
> kill -CONT -"$PGID"  # awake stopped processes
> kill -KILL -"$PGID"  # kill -9 to be sure

> ps fj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
28348 28349 28349 28349 pts/3    29039 Ss   33021   0:00 -bash
28349 29039 29039 28349 pts/3    29039 R+   33021   0:00  \_ ps fj

Schlussfolgerung

Ich bemerke in diesem Beispiel PID und PGID gleich sind (28957 ).
Deshalb dachte ich ursprünglich an kill -- -$PID war genug. Aber in dem Fall wird der Prozess innerhalb eines Makefile erzeugt die Prozess-ID unterscheidet sich von der Gruppen-ID .

Ich denke kill -- -$(ps -o pgid= $PID | grep -o [0-9]*) ist der beste einfache Trick, um einen ganzen Prozessbaum zu beenden, wenn er von einer anderen Gruppen-ID aufgerufen wird (ein weiterer Prozessbaum).


pkill -TERM -P 27888

Dadurch werden alle Prozesse beendet, die die übergeordnete Prozess-ID 27888 haben.

Oder robuster:

CPIDS=$(pgrep -P 27888); (sleep 33 && kill -KILL $CPIDS &); kill -TERM $CPIDS

die das Töten 33 Sekunden später planen und Prozesse höflich bitten, sich zu beenden.

Siehe diese Antwort zum Beenden aller Nachkommen.


Linux
  1. Was bedeuten unter Linux alle Werte im obersten Befehl?

  2. Was ist der beste Weg, um Dateien nach dem Teilen wieder zusammenzuführen?

  3. Wie lernt man SELinux am besten?

  4. Was ist der Unterschied zwischen kill, pkill und killall?

  5. Was ist der schnellste Weg, um alle Dateien und Unterordner in einem Verzeichnis zu entfernen?

So listen Sie die Mitglieder einer Gruppe in Linux auf

Linux – Kann Strg+c das Sigint-Signal an mehrere Prozesse senden?

SIGTERM vs. SIGKILL:Was ist der Unterschied?

Was ist der Kill-Befehl in Linux?

Was ist ein gestoppter Prozess unter Linux?

Was ist der beste Weg, um zu überprüfen, ob ein Volume in einem Bash-Skript gemountet ist?