GNU/Linux >> Belajar Linux >  >> Linux

Apa cara terbaik untuk mengirim sinyal ke semua anggota grup proses?

Anda tidak mengatakan jika pohon yang ingin Anda bunuh adalah grup proses tunggal. (Hal ini sering terjadi jika pohon adalah hasil percabangan dari awal server atau baris perintah shell.) Anda dapat menemukan grup proses menggunakan GNU ps sebagai berikut:

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

Jika ini adalah grup proses yang ingin Anda matikan, cukup gunakan kill(1) perintah tetapi alih-alih memberinya nomor proses, berikan negasi dari nomor kelompok. Misalnya untuk mematikan setiap proses di grup 5112, gunakan kill -TERM -- -5112 .


Bunuh semua proses yang termasuk dalam pohon proses yang sama menggunakan ID Grup Proses (PGID )

  • kill -- -$PGID Gunakan sinyal default (TERM =15)
  • kill -9 -$PGID Gunakan sinyal KILL (9)

Anda dapat mengambil PGID dari Process-ID apa pun (PID ) dari pohon proses yang sama

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

Penjelasan

  • kill -9 -"$PGID" => Kirim sinyal 9 (KILL ) untuk semua anak dan cucu...
  • PGID=$(ps opgid= "$PID") => Ambil Process-Group-ID dari Process-ID apa pun pohon, bukan hanya Process-Parent-ID . Variasi dari ps opgid= $PID adalah ps -o pgid --no-headers $PID di mana pgid dapat diganti dengan pgrp .
    Tapi:
    • ps menyisipkan spasi di depan saat PID kurang dari lima digit dan rata kanan seperti yang diperhatikan oleh tanager. Kamu dapat memakai:
      PGID=$(ps opgid= "$PID" | tr -d ' ')
    • ps dari OSX selalu cetak header, oleh karena itu Speakus mengusulkan:
      PGID="$( ps -o pgid "$PID" | grep [0-9] | tr -d ' ' )"
  • grep -o [0-9]* hanya mencetak digit berurutan (tidak mencetak spasi atau header abjad).

Baris perintah lebih lanjut

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)

Batasan

  • Seperti yang diperhatikan oleh davide dan Hubert Kario, saat kill dipanggil oleh proses milik pohon yang sama, kill berisiko bunuh diri sebelum menghentikan seluruh pembunuhan pohon.
  • Oleh karena itu, pastikan untuk menjalankan perintah menggunakan proses yang memiliki Process-Group-ID yang berbeda .

Ceritanya panjang

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

Jalankan pohon proses di latar belakang menggunakan '&'

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

Perintah pkill -P $PID tidak membunuh cucu:

> 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

Perintah kill -- -$PGID membunuh semua proses termasuk cucu.

> 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

Kesimpulan

Saya perhatikan dalam contoh ini PID dan PGID sama (28957 ).
Inilah mengapa saya awalnya berpikir kill -- -$PID sudah cukup. Namun dalam kasus proses tersebut muncul dalam Makefile ID Proses berbeda dengan ID Grup .

Saya pikir kill -- -$(ps -o pgid= $PID | grep -o [0-9]*) adalah trik sederhana terbaik untuk mematikan seluruh pohon proses saat dipanggil dari ID Grup yang berbeda (pohon proses lain).


pkill -TERM -P 27888

Ini akan menghentikan semua proses yang memiliki ID proses induk 27888.

Atau lebih kuat:

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

yang menjadwalkan membunuh 33 detik kemudian dan dengan sopan meminta proses untuk dihentikan.

Lihat jawaban ini untuk menghentikan semua turunan.


Linux
  1. Proses apa yang menggunakan semua IO disk saya

  2. Apa cara terbaik untuk menangani kondisi kehabisan memori di Jawa?

  3. Linux:cari tahu proses apa yang menggunakan semua RAM?

  1. Apa cara terbaik untuk menggabungkan kembali file setelah memisahkannya?

  2. Apa cara terbaik untuk mempelajari SELinux?

  3. Apa perbedaan antara kill , pkill dan killall?

  1. Linux – Bisakah Ctrl+c Mengirim Sinyal Tanda Ke Beberapa Proses?

  2. Apa cara tercepat untuk menghapus semua file &subfolder dalam direktori?

  3. Apa cara terbaik untuk memeriksa apakah volume dipasang di skrip Bash?