GNU/Linux >> Znalost Linux >  >> Linux

Jaký je nejlepší způsob, jak vyslat signál všem členům procesní skupiny?

Neříkáte, zda je strom, který chcete zabít, jedinou skupinou procesů. (To je často případ, kdy je strom výsledkem rozvětvení ze spuštění serveru nebo příkazového řádku shellu.) Skupiny procesů můžete zjistit pomocí GNU ps následovně:

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

Pokud chcete ukončit skupinu procesů, stačí použít kill(1) ale místo čísla procesu mu dejte negaci čísla skupiny. Chcete-li například zabít každý proces ve skupině 5112, použijte kill -TERM -- -5112 .


Zabijte všechny procesy patřící do stejného stromu procesů pomocí ID skupiny procesů (PGID )

  • kill -- -$PGID Použít výchozí signál (TERM =15)
  • kill -9 -$PGID Použijte signál KILL (9)

Můžete získat PGID z libovolného ID procesu (PID ) stejného stromu procesů

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

Vysvětlení

  • kill -9 -"$PGID" => Odeslat signál 9 (KILL ) všem dětem a vnoučatům...
  • PGID=$(ps opgid= "$PID") => Získejte ID skupiny procesů z libovolného ID procesu stromu, nejen Process-Parent-ID . Varianta ps opgid= $PID je ps -o pgid --no-headers $PID kde pgid lze nahradit pgrp .
    Ale:
    • ps vloží úvodní mezery, když PID je méně než pět číslic a je zarovnáno vpravo, jak si všiml tanager. Můžeš použít:
      PGID=$(ps opgid= "$PID" | tr -d ' ')
    • ps z OSX vždy tiskněte záhlaví, proto Speakus navrhuje:
      PGID="$( ps -o pgid "$PID" | grep [0-9] | tr -d ' ' )"
  • grep -o [0-9]* vytiskne pouze po sobě jdoucí číslice (netiskne mezery ani abecední záhlaví).

Další příkazové řádky

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)

Omezení

  • Jak si všimli davide a Hubert Kario, když kill je vyvolán procesem, který patří do stejného stromu, kill riskuje, že se zabije, než ukončí zabíjení celého stromu.
  • Proto se ujistěte, že příkaz spouštíte pomocí procesu, který má jiné Process-Group-ID .

Dlouhý příběh

> 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)"

Spusťte strom procesů na pozadí pomocí '&'

> ./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

Příkaz pkill -P $PID nezabije vnouče:

> 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

Příkaz kill -- -$PGID zabije všechny procesy včetně vnuka.

> 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

Závěr

V tomto příkladu jsem si všiml PID a PGID jsou stejné (28957 ).
To je důvod, proč jsem původně myslel kill -- -$PID bylo dost. Ale v případě, že je proces spawnován v Makefile ID procesu se liší od ID skupiny .

Myslím, že kill -- -$(ps -o pgid= $PID | grep -o [0-9]*) je nejlepší jednoduchý trik, jak zabít celý procesový strom, když je volán z jiného ID skupiny (jiný procesní strom).


pkill -TERM -P 27888

To ukončí všechny procesy, které mají ID rodičovského procesu 27888.

Nebo robustnější:

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

které naplánují zabíjení o 33 sekund později a zdvořile požádají procesy o ukončení.

Viz tato odpověď pro ukončení všech potomků.


Linux
  1. Linux – Může Ctrl+c odeslat signál Sigint více procesům?

  2. Jaký proces používá celý můj disk IO

  3. Linux:zjistěte, jaký proces využívá všechnu RAM?

  1. Kdy systém odešle SIGTERM procesu?

  2. Jaký je nejlepší způsob, jak se naučit SELinux?

  3. Jaký je nejrychlejší způsob odstranění všech souborů a podsložek v adresáři?

  1. Jaký je nejlepší způsob, jak nastavit proměnnou prostředí v .bashrc?

  2. Jaký je nejlepší způsob zpracování oprávnění pro uživatele www-data Apache 2 v /var/www?

  3. Jaký je nejlepší způsob, jak získat informace o aktuálně nepřipojených jednotkách?