ฆ่ากระบวนการทั้งหมดที่ทำงานนานกว่า 5 นาทีโดยผู้ใช้ที่กำหนดในสคริปต์ linux bash


18

ฉันต้องการคำสั่งเพื่อฆ่าโปรเซสที่รันอยู่อย่างน้อย 5 นาทีสำหรับกระบวนการที่กำหนด

ฉันจะต้องเรียกใช้คำสั่งนั้นทุก ๆ ห้านาทีหรือมากกว่านั้น

ขอบคุณหนึ่งล้าน!

(ระบบคือ Centos5)

linux  bash 

คำตอบ:


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

โดยที่ "procname" เป็นชื่อกระบวนการและ 300 กำลังเรียกใช้ขีด จำกัด เวลา


เยี่ยมมาก ๆ ฉันใช้มันโดยไม่-9เป็นมิตรกับกระบวนการของฉันและเพิ่ม a grep -v defunct |ก่อนหน้านี้awkเมื่อคุณเห็นprocname <defunct>ในผลลัพธ์ของคุณซึ่งจะทำให้คำสั่ง awk ไม่ส่งคืน PID ที่ถูกต้อง และนี่จะทำลายคำสั่ง kill
Michael Härtl

ฉันจะบอกว่า$(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')เรียบเนียนขึ้นเล็กน้อย แต่คำตอบนั้นยอดเยี่ยมอยู่ดี
Yevgen

@ WhiteHat วิธีการทำสิ่งเดียวกัน แต่สำหรับกระบวนการที่มี pid?
Petar Vasilev

สิ่งหนึ่งที่ทำให้ฉันเสียเวลาคือ: ควรใช้ 'ด้วย awk ไม่ "
cn123h

6

อาจจะรันคำสั่งที่ใช้เวลานานเช่นนี้ใน crontab หรือไม่?

timeout -k 300 command

5

สคริปต์การฆ่าเวอร์ชันของฉันได้รับประโยชน์จากคำตอบก่อนหน้านี้ทั้งสอง:

#!/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

มันกรองกระบวนการโดย UID, NAME และถ้าเวลาดำเนินการเกินขีด จำกัด - ฆ่ากระบวนการและส่งรายงานไปยังอีเมล หากคุณไม่ต้องการอีเมลดังกล่าวคุณสามารถแสดงความคิดเห็นบรรทัดสุดท้าย


2

ฉันพบวิธีแก้ปัญหาในหน้านี้: http://www.directadmin.com/forum/showthread.php?t=26179

ทำไฟล์ว่างและเรียกมันว่า killlongproc.sh

คัดลอกนี้:

#!/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;

หยุดสิ่งนี้ใน cronjob ของคุณ

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

4
มันเป็นความคิดที่ดีที่จะทำสิ่งนี้ คุณพยายามแก้ไขปัญหาอะไรจริงๆ นอกจากนี้คุณไม่ควรใช้kill -9เนื่องจากจะไม่ทำให้กระบวนการมีโอกาสทำความสะอาดอย่างนุ่มนวลก่อนออก
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

1
กระบวนการนี้ฆ่ากระบวนการซึ่งใช้เวลา CPU จำนวนหนึ่ง (ผู้ใช้ + ระบบ) ไม่ใช่กระบวนการที่กำลังทำงานตามเวลาจริง (เช่นเริ่มต้นก่อน 1 ชั่วโมง)
Marki555

2

มีสคริปต์ที่นี่ที่คุณสามารถปรับเปลี่ยนเพื่อทำสิ่งที่คุณต้องการ

EDIT เพิ่มสคริปต์ด้านล่าง

#!/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

ฉันไม่มีความรู้เพียงพอที่จะปรับเปลี่ยนนั่นคือเหตุผลที่ฉันขอให้คุณ

2
ซับซ้อนเกินไป. คุณสามารถใช้คอลัมน์etimesของpsเพื่อแสดงวินาทีที่ผ่านไปโดยตรงตั้งแต่เริ่มต้นกระบวนการ (ไม่จำเป็นต้องคำนวณนับตั้งแต่เวลาเริ่มต้น)
Marki555

@ Marki555 ใช่นี่เป็นความจริง อย่างไรก็ตามในระบบที่มีรุ่นpsที่ไม่รองรับetimes(เท่านั้นetime) นี่เป็นทางเลือกที่ยอดเยี่ยม ฉันเพิ่งใช้มันเมื่อคำตอบยอดนิยมทำให้ฉันมีข้อผิดพลาดจากps
ไมค์

0

ฉันต้องแก้งานที่คล้ายกันและไม่จำเป็นต้องมีสคริปต์ สำหรับกระบวนการยุติ (สัญญาณ SIGTERM) ของปฏิบัติการ "THECOMMAND":

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

การ จำกัด ผู้ใช้ปัจจุบัน-u $USERจำเป็นเฉพาะเพื่อหลีกเลี่ยงข้อความแสดงข้อผิดพลาดที่ไม่จำเป็นหากผู้ใช้รายอื่นเรียกใช้ "THECOMMAND" ด้วย ใน crontab ผู้ใช้ของคุณคุณจะต้องป้อนสิ่งต่อไปนี้:

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

ในระบบ crontab (ผู้ใช้ 'รูท') คุณจะเพิ่มสิ่งต่อไปนี้:

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

หากคุณต้องการฆ่า (SIGKILL) กระบวนการแทนที่จะยุติ (SIGTERM) ให้ส่งสัญญาณ SIGKILL อย่างชัดเจนโดยการเพิ่ม--signal SIGKILLพารามิเตอร์ ตัวอย่างสำหรับ crontab ระบบ:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.