Bunuh semua proses yang berjalan selama lebih dari 5 menit oleh pengguna yang diberikan dalam skrip bash linux


18

Saya memerlukan perintah untuk mematikan proses yang telah berjalan setidaknya 5 menit untuk proses yang diberikan.

Saya harus menjalankan perintah itu setiap lima menit atau lebih.

Terima kasih banyak !

(sistem adalah Centos5)

linux  bash 

Jawaban:


17
kill -9 $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print $2}}')

di mana "procname" adalah nama proses dan 300 menjalankan ambang waktu


Oneliner hebat. Saya telah menggunakannya tanpa -9menjadi sedikit lebih ramah dengan proses saya dan menambahkan grep -v defunct |sebelumnya awksebagai otherwhise Anda mungkin melihat procname <defunct>dalam output Anda yang akan membuat perintah awk tidak mengembalikan PID yang valid. Dan ini akan melanggar perintah membunuh.
Michael Härtl

saya akan mengatakan $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')sedikit lebih halus tetapi jawabannya bagus
Yevgen

@ WhiteHat bagaimana melakukan hal yang sama tetapi untuk proses dengan pid tertentu?
Petar Vasilev

satu hal yang menyia-nyiakan waktu saya adalah: harus menggunakan 'dengan awk TIDAK "
cn123h

6

Mungkin menjalankan perintah berjalan lama seperti ini di crontab?

timeout -k 300 command

5

Versi skrip kill saya, mengambil manfaat dari kedua jawaban sebelumnya:

#!/bin/bash

#Email to send report
MY_EMAIL="example@email.com"

#Process name to kill
NAME_KILL="php"

#UID to kill
UID_KILL=33.

#Time in seconds which the process is allowed to run
KILL_TIME=60

KILL_LIST=()
EMAIL_LIST=()
while read PROC_UID PROC_PID PROC_ETIMES PROC_ETIME PROC_COMM PROC_ARGS; do
    if [ $PROC_UID -eq $UID_KILL -a "$PROC_COMM" == "$NAME_KILL" -a $PROC_ETIMES -gt $KILL_TIME ]; then
    KILL_LIST+=("$PROC_PID");
    MSG="Killing '$PROC_ARGS' which runs for $PROC_ETIME";
    EMAIL_LIST+=("$MSG");
    echo "$MSG";
    fi
done < <(ps eaxo uid,pid,etimes,etime,comm,args | tail -n+2)
if [ ${#KILL_LIST[*]} -gt 0 ]; then
    kill -9 ${KILL_LIST[@]}
    printf '%s\n' "${EMAIL_LIST[@]}" | mail -s "Long running processes killed" $MY_EMAIL
fi

Ini memfilter proses oleh UID, NAME dan jika waktu eksekusi melebihi batas - bunuh proses dan kirim laporan ke email. Jika Anda tidak memerlukan email itu - Anda bisa mengomentari baris terakhir.


2

Saya menemukan solusinya di halaman ini: http://www.directadmin.com/forum/showthread.php?t=26179

Buat file kosong dan sebut itu killlongproc.sh

Salin ini:

#!/bin/bash
# This script will kill process which running more than X hours
# egrep: the selected process; grep: hours
PIDS="`ps eaxo bsdtime,pid,comm | egrep "spamd|exim|mysqld|httpd" | grep " 1:" | awk '{print $2}'`"

# Kill the process
echo "Killing spamd, exim, mysqld and httpd processes running more than one hour..."
for i in ${PIDS}; do { echo "Killing $i"; kill -9 $i; }; done;

Hentikan ini di cronjob Anda

15 * * * * * root /{directory}/./killongproc.sh

4
Ini biasanya ide yang buruk untuk melakukan ini. Masalah apa yang sebenarnya ingin Anda pecahkan? Selain itu, Anda tidak boleh menggunakannya kill -9karena tidak memberikan proses kesempatan untuk melakukan pembersihan dengan anggun sebelum keluar.
Dijeda sampai pemberitahuan lebih lanjut.

1
Ini membunuh proses yang menghabiskan sejumlah waktu CPU (sistem pengguna +), bukan proses yang berjalan untuk sejumlah waktu nyata (misalnya dimulai sebelum 1 jam).
Marki555

2

Ada skrip di sini yang dapat Anda modifikasi untuk melakukan apa yang Anda inginkan.

EDIT menambahkan skrip di bawah ini

#!/bin/bash
#
#Put the UID to kill on the next line
UID_KILL=1001

#Put the time in seconds which the process is allowed to run below
KILL_TIME=300

KILL_LIST=`{
ps -eo uid,pid,lstart | tail -n+2 |
    while read PROC_UID PROC_PID PROC_LSTART; do
        SECONDS=$[$(date +%s) - $(date -d"$PROC_LSTART" +%s)]
        if [ $PROC_UID -eq $UID_KILL -a $SECONDS -gt $KILL_TIME ]; then
        echo -n "$PROC_PID "
        fi
     done 
}`

if [[ -n $KILL_LIST ]]
then
        kill $KILL_LIST
fi

Saya tidak memiliki pengetahuan yang cukup untuk memodifikasinya, itu sebabnya saya meminta Anda

2
Terlalu rumit. Anda dapat menggunakan kolom etimesdari psmenunjukkan secara langsung detik-detik berlalu sejak proses awal (tidak perlu menghitung dari waktu mulai).
Marki555

@ Marki555 ya ini benar. Namun pada sistem dengan versi psyang tidak mendukung etimes(hanya etime) maka ini merupakan alternatif yang bagus. Saya hanya menggunakannya ketika jawaban teratas memberi saya kesalahan darips
mike

0

Saya harus menyelesaikan tugas yang sama, dan tidak perlu skrip. Untuk mengakhiri (sinyal SIGTERM) proses yang dapat dieksekusi "THECOMMAND":

killall -u $USER --older-than 5m THECOMMAND

Pembatasan untuk pengguna saat -u $USERini diperlukan hanya untuk menghindari pesan kesalahan yang tidak perlu jika pengguna lain juga menjalankan "THECOMMAND". Di crontab pengguna Anda sendiri, Anda akan memasukkan yang berikut ini:

*/5 * * * *     killall -u $USER --older-than 5m THECOMMAND

Dalam crontab sistem (pengguna 'root') Anda akan menambahkan yang berikut:

*/5 * * * *     killall --older-than 5m THECOMMAND

Jika Anda ingin membunuh (SIGKILL) proses alih-alih menghentikan (SIGTERM) mereka, secara eksplisit mengirim sinyal SIGKILL dengan menambahkan --signal SIGKILLke parameter. Contoh untuk sistem crontab:

*/5 * * * *     killall --older-than 5m --signal SIGKILL THECOMMAND

-4

Untuk httpd

ps eaxo pid, waktu, komunikasi | tail -n + 2 | grep 'httpd' | awk 'substr ($ 0,9,1)> 0' | awk '{print $ 1}'

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.