สคริปต์ทุบตีที่ฆ่ากระบวนการโดยอัตโนมัติเมื่อการใช้งาน CPU / หน่วยความจำสูงเกินไป


11

ฉันได้สร้างสคริปต์ที่ฆ่ากระบวนการหากใช้งาน CPU และ / หรือหน่วยความจำถึง 80% มันสร้างรายการของกระบวนการที่ถูกฆ่าเมื่อเกิดเหตุการณ์นี้ขึ้น ฉันจะปรับปรุงอะไรได้บ้าง

while [ 1 ];
do 
echo
echo checking for run-away process ...

CPU_USAGE=$(uptime | cut -d"," -f4 | cut -d":" -f2 | cut -d" " -f2 | sed -e "s/\.//g")
CPU_USAGE_THRESHOLD=800
PROCESS=$(ps aux r)
TOPPROCESS=$(ps -eo pid -eo pcpu -eo command | sort -k 2 -r | grep -v PID | head -n 1)

if [ $CPU_USAGE -gt $CPU_USAGE_THRESHOLD] ; then
  kill -9 $(ps -eo pid | sort -k 1 -r | grep -v PID | head -n 1) #original
  kill -9 $(ps -eo pcpu | sort -k 1 -r | grep -v %CPU | head -n 1)
  kill -9 $TOPPROCESS
  echo system overloading!
  echo Top-most process killed $TOPPROCESS
      echo CPU USAGE is at $CPU_LOAD

else
    fi
    exit 0
    sleep 1;
    done

3
คุณลองเรียกใช้สคริปต์แล้วหรือยัง while [ 1 ]ทำให้ฉันสงสัยว่าสคริปต์ตัวนี้จะกินซีพียูเท่าไร นอกจากนี้ 3 สายkill -9ในสคริปต์ทำงานอย่างต่อเนื่อง? นี่ทำให้ฉันรู้สึกหนาวสั่น ...
rahmu

1
อวตารที่ดีต่อไป @rahmu เขาได้sleep 1ในวง
เดซี่

1
วันจันทร์แรกของเดือนและพีซีของฉันกำลังตรวจสอบชุด RAID6 ที่ 'ช้า' โหลด CPU สูงกว่า 8 อย่างง่ายดายเพราะมันกำลังรอดิสก์ IO จากชุด RAID นี้อย่างต่อเนื่อง ไม่มีอะไรผิดปกติระบบยังตอบสนองได้ดีมาก สคริปต์ของคุณจะฆ่า Firefox ของฉันซึ่งใช้เพียง 3.6% จากที่มีอยู่ 400% แค่บอกว่าคุณอาจจะตามล่าหาผีด้วยสคริปต์นี้ BTW: ระบบของคุณจะไม่ได้รับความเสียหายเนื่องจากการโหลดสูงและเมื่อหน่วยความจำหมดเคอร์เนลจะทำการเดาแบบกึ่งทางการศึกษาว่ากระบวนการใดที่จะฆ่า
jippie

จากนั้นขั้นตอนการฆ่าตามโหลดจะเป็นเรื่องปกติหรือไม่ ???
Ketan Patel

ในกรณีของฉันการใช้งานไม่ต้องการการฆ่า
jippie

คำตอบ:


11

ฉันคาดเดาปัญหาที่คุณต้องการแก้คือคุณมีกระบวนการบางอย่างที่ทำงานอยู่ในกล่องของคุณซึ่งบางครั้งก็ทำงานผิดปกติ

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

อย่างน้อยที่สุดคุณต้องการ จำกัด สคริปต์ของคุณเฉพาะโปรแกรมเดียวที่คุณกังวล จะเป็นการดีที่สุดถ้าสิทธิ์ จำกัด สคริปต์ของคุณเช่นนี้ (เช่นสคริปต์ของคุณทำงานในฐานะผู้ใช้ X สิ่งเดียวที่ทำงานเป็น X คือโปรแกรม)

ยิ่งไปกว่านั้นก็คือการใช้สิ่งที่ต้องการulimit -tจำกัด จำนวนเวลา CPU ทั้งหมดที่โปรแกรมสามารถใช้ได้ ulimit -vในทำนองเดียวกันถ้ามันกินหน่วยความจำทั้งหมดที่ตรวจสอบ เคอร์เนลบังคับใช้ข้อ จำกัด เหล่านี้ ดูbashmanpage (เป็นเชลล์ในตัว) และsetrlimit(2)manpage สำหรับรายละเอียด

หากปัญหาไม่ได้เป็นกระบวนการที่กำลังทำงานอยู่ แต่เป็นเพียงกระบวนการที่กำลังทำงานอยู่มากเกินไปดังนั้นให้ใช้รูปแบบการล็อกบางอย่างเพื่อป้องกันไม่ให้ X มากกว่าการทำงาน (หรือ - สิ่งนี้ควรทำความคุ้นเคย - ulimit -u) นอกจากนี้คุณยังอาจพิจารณาเปลี่ยนลำดับความสำคัญของการจัดตารางเวลาของกระบวนการเหล่านั้น (ใช้niceหรือrenice) หรือแม้รุนแรงมากขึ้นโดยใช้การเปลี่ยนแปลงนโยบายที่จะsched_setschedulerSCHED_IDLE

หากคุณต้องการการควบคุมที่มากยิ่งขึ้นลองดูกลุ่มควบคุม (กลุ่ม cg) ขึ้นอยู่กับเคอร์เนลที่คุณใช้งานคุณสามารถ จำกัด จำนวนเวลา CPU, หน่วยความจำ, I / O, ฯลฯ ที่กระบวนการทั้งกลุ่มใช้ร่วมกัน กลุ่มควบคุมค่อนข้างยืดหยุ่น พวกเขาสามารถทำสิ่งที่คุณพยายามทำได้โดยไม่ต้องมีบากอันบอบบาง Arch Linux Wiki มีข้อมูลเบื้องต้นเกี่ยวกับ cgroupsที่ควรค่าแก่การอ่านเช่นเดียวกับซีรี่ส์ cgroups ของ Neil Brownที่ LWN


3

ปัญหาที่พบ:

  • เมื่อเรียงลำดับช่องตัวเลขคุณอาจต้องการที่จะใช้ตัวเลือก:-n sort -nrk 2มิฉะนั้นบรรทัดที่มี%CPUค่า 5.0 จะสิ้นสุดสูงกว่าหนึ่งบรรทัดที่มีค่า 12.0
  • ทั้งนี้ขึ้นอยู่กับpsการดำเนินการที่คุณอาจต้องการที่จะใช้ตัวเลือกที่จะได้รับการกำจัดของ--no-headers ป้องกันคุณจากการที่คำสั่งทิ้งที่มีgrep -vPID
  • ฉันเดาแทนคุณหมายecho CPU USAGE is at $CPU_LOADecho CPU USAGE is at $CPU_USAGE
  • ฉันเดาว่าคุณลืมลบสิ่งexit 0ที่คุณแทรกระหว่างการดีบั๊ก (?)

สไตล์:

  • คุณอาจต้องการย้ายCPU_USAGE_THRESHOLD=800บรรทัดไปยังจุดเริ่มต้นของไฟล์เนื่องจากเป็นสิ่งที่ให้ข้อมูลมากที่สุดและมีแนวโน้มที่จะเปลี่ยนไปแม้หลังจากที่สคริปต์ของคุณมีเสถียรภาพ
  • คุณกำลังทำซ้ำ-eตัวเลือก: ps -eo pid -eo pcpu -eo commandเป็นเช่นเดียวกับps -eo pid -o pcpu -o command(ตามที่เป็นps -eo pid,pcpu,command)
  • มีelseประโยคว่างเปล่า ดูเหมือนจะเป็นว่าควรจัดการ แต่ไม่ใช่ด้วยเหตุผลที่ไม่ทราบสาเหตุ

2

การฆ่ากระบวนการที่ใช้ CPU / หน่วยความจำส่วนใหญ่เป็นการถามถึงปัญหา: เพียงแค่ดูว่าตอนนี้มันมีอะไรบ้างในเครื่องของคุณ (ที่นี่คือ firefox, systemd (init), Xorg, gnome-terminal, ชุดของเคอร์เนลเธรด ไม่มีสิ่งใดที่สามารถแจกจ่ายได้) ดูวิธีการปรับแต่งลินุกซ์' OOM ฆ่ายกตัวอย่างเช่นที่นี่

นอกจากนี้โปรดทราบว่า "หน่วยความจำที่ใช้โดยกระบวนการ" เป็นแนวคิดที่คลุมเครือเนื่องจากมีไลบรารีที่แบ่งใช้ไฟล์ที่เรียกทำงานได้จะถูกแชร์และแม้แต่ส่วนของพื้นที่ข้อมูล หนึ่งสามารถเกิดขึ้นกับหมายเลขบางส่วนโดยการชาร์จผู้ใช้แต่ละคนด้วยเศษส่วนของพื้นที่ที่ใช้ แต่แม้กระทั่งการเพิ่มขึ้นนั้นไม่ได้ให้ "หน่วยความจำที่ใช้" (หน่วยความจำที่ใช้น้อยลง) ที่อยู่เบื้องหลัง)


1

ฉันสร้างสคริปต์kill-processซึ่งฆ่ากระบวนการบางอย่างที่ระบุไว้ในอาร์เรย์ถ้าการใช้งาน CPU มากกว่า XX% สำหรับ YY วินาทีหรือกระบวนการ kill ที่ทำงานมากกว่า ZZ วินาที

  • คุณสามารถตั้งค่า XX, YY, ZZ ที่ด้านบนของไฟล์
  • คุณสามารถใช้ ps หรือ top สำหรับตรวจสอบกระบวนการ
  • มีโหมดเรียกใช้แบบแห้งเพื่อตรวจสอบ แต่ไม่ฆ่า
  • ในที่สุดสคริปต์จะส่งอีเมลหากกระบวนการบางอย่างถูกฆ่า

หมายเหตุ:นี่คือ repo ของฉันใน Github: https://github.com/padosoft/kill-process

นี่คือภาพหน้าจอ:

         เอสเอส # 1

อ้างอิง

ส่วนสำคัญของสคริปต์ (รหัสย่อมาจากคำสั่งด้านบน):

#!/usr/bin/env bash

#max cpu % load
MAX_CPU=90
#max execution time for CPU percentage > MAX_CPU (in seconds 7200s=2h)
MAX_SEC=1800
#sort by cpu
SORTBY=9

#define a processes command name to check
declare -a KILLLIST
KILLLIST=("/usr/sbin/apache2" "/usr/bin/php5-cgi")

#iterate for each process to check in list
for PROCESS_TOCHECK in ${KILLLIST[*]}
do

    #retrive pid with top command order by SORTBY
    PID=$(top -bcSH -n 1 | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $1}')

    CPU=$(top -p $PID -bcSH -n 1 | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $9}')
    TIME_STR=$(top -p $PID -bcSH -n 1 | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $11}')

    # Decode the top CPU time format [dd-]hh:mm.ss.
    TIME_SEC=0
    IFS="-:" read c1 c2 c3 c4 <<< "$TIME_STR"

    #with top command time format is hh:mm.ss, so truncare seconds in c2
    c2=${c2%%.*}

    if [ -n "$c4" ]
    then
      TIME_SEC=$((10#$c4+60*(10#$c3+60*(10#$c2+24*10#$c1))))
    elif [ -n "$c3" ]
    then
      if [ "$CMD" = "ps" ]; then
        TIME_SEC=$((10#$c3+60*(10#$c2+60*10#$c1)))
      else
        TIME_SEC=$(((10#$c3*24)*60*60)+60*(10#$c2+60*10#$c1))             
      fi   
    else
      if [ "$CMD" = "ps" ]; then
        TIME_SEC=$((10#0+(10#$c2+60*10#$c1)))
      else
        TIME_SEC=$((10#0+60*(10#$c2+60*10#$c1)))
      fi
    fi

    #check if need to kill process
    if [ $CPU -gt $MAX_CPU ] && [ $TIME_SEC -gt $MAX_SEC ]; then
        kill -15 $PID
    fi

done
การใช้งาน:
bash killprocess.sh [dry|kill|--help] [top|ps] [cpu|time]

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