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.