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 sinyalKILL
(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]*')
(sinyalTERM
)kill -9 -$(ps -o pgid= $PID | grep -o '[0-9]*')
(sinyalKILL
)
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 darips opgid= $PID
adalahps -o pgid --no-headers $PID
di manapgid
dapat diganti denganpgrp
.
Tapi:ps
menyisipkan spasi di depan saatPID
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.