Skrip Bash yang secara otomatis membunuh proses ketika penggunaan CPU / memori menjadi terlalu tinggi

11

Saya telah membuat skrip yang membunuh proses jika penggunaan CPU dan / atau memori mencapai 80%. Itu membuat daftar proses yang terbunuh ketika ini terjadi. Apa yang bisa saya lakukan untuk memperbaikinya?

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
Ketan Patel
sumber
3
Sudahkah Anda mencoba menjalankan skrip? while [ 1 ]membuat saya bertanya-tanya berapa banyak CPU script ini akan mengkonsumsi. Juga, 3 panggilan ke kill -9dalam skrip berjalan terus? Ini membuatku merinding ...
rahmu
1
Lagipula avatar yang bagus, @rahmu dia mendapat sleep 1di loop
daisy
1
Senin pertama bulan ini dan PC saya sedang memeriksa set RAID6 (lambat). CPU memuat dengan mudah puncak di atas 8 karena selalu menunggu disk IO dari set RAID ini. Tidak ada salahnya, sistem masih sangat responsif. Script Anda akan mematikan firefox saya yang hanya menggunakan 3,6% dari 400% yang tersedia. Hanya mengatakan Anda mungkin berburu hantu dengan skrip ini. BTW: sistem Anda tidak akan rusak karena beban tinggi dan ketika kehabisan memori, kernel akan melakukan tebakan semi-berpendidikan tentang proses mana yang harus dimatikan.
jippie
Kemudian proses kill berdasarkan beban akan baik-baik saja atau tidak ????
Ketan Patel
Dalam kasus penggunaan saya pembunuhan tidak diinginkan.
jippie

Jawaban:

11

Saya menebak masalah yang ingin Anda pecahkan adalah bahwa Anda memiliki beberapa proses yang berjalan di komputer anda yang kadang-kadang bertingkah, dan duduk selamanya mengelompokkan inti.

Hal pertama yang ingin Anda lakukan adalah mencoba memperbaiki program yang menjadi gila. Sejauh ini solusi terbaik. Saya akan berasumsi itu tidak mungkin, atau Anda perlu kluge cepat untuk menjaga kotak Anda berjalan sampai diperbaiki.

Anda, setidaknya, ingin membatasi skrip Anda hanya untuk menekan satu program yang Anda khawatirkan. Akan lebih baik jika izin membatasi skrip Anda seperti ini (mis. Skrip Anda berjalan sebagai pengguna X, satu-satunya hal lain yang berjalan sebagai X adalah programnya).

Bahkan lebih baik menggunakan sesuatu seperti ulimit -tmembatasi jumlah total waktu CPU yang dapat digunakan oleh program. Demikian pula, jika menghabiskan semua memori, periksa ulimit -v. Kernel memberlakukan batasan ini; lihat halaman bashmanual (ini adalah built-in shell) dan halaman setrlimit(2)manual untuk detailnya.

Jika masalahnya bukan proses yang berjalan mengamuk, tetapi justru terlalu banyak proses yang berjalan, maka terapkan beberapa bentuk penguncian untuk mencegah lebih dari X dari menjalankan (atau — ini seharusnya menjadi akrab— ulimit -u). Anda juga dapat mempertimbangkan untuk mengubah prioritas penjadwal proses-proses tersebut (menggunakan niceatau renice), atau bahkan lebih drastis, menggunakan sched_setscheduleruntuk mengubah kebijakan SCHED_IDLE.

Jika Anda membutuhkan lebih banyak kontrol, lihat grup kontrol (cgroups). Bergantung pada kernel yang Anda jalankan, Anda sebenarnya dapat membatasi jumlah waktu CPU, memori, I / O, dll. Yang dikonsumsi oleh seluruh kelompok proses secara bersamaan. Kelompok kontrol cukup fleksibel; mereka mungkin dapat melakukan apa pun yang Anda coba lakukan, tanpa klasp yang rapuh. Arch Linux Wiki memiliki pengantar untuk cgroup yang layak dibaca, seperti halnya seri cgroup Neil Brown di LWN.

derobert
sumber
3

Masalah:

  • Ketika menyortir bidang numerik Anda mungkin ingin menggunakan -nopsi: sort -nrk 2. Kalau tidak, garis dengan %CPUnilai 5.0 akan berakhir lebih tinggi dari satu dengan nilai 12.0.
  • Tergantung pada psimplementasi Anda, Anda mungkin ingin menggunakan --no-headersopsi untuk menyingkirkan grep -v. Itu mencegah Anda membuang perintah yang berisi PID.
  • Saya kira, bukan echo CPU USAGE is at $CPU_LOAD, maksud Anda echo CPU USAGE is at $CPU_USAGE.
  • Saya kira Anda lupa menghapus exit 0yang Anda masukkan saat debugging (?).

Gaya:

  • Anda mungkin ingin memindahkan CPU_USAGE_THRESHOLD=800baris ke awal file, karena ini hal yang paling informatif dan kemungkinan besar akan berubah bahkan setelah skrip Anda stabil.
  • Anda mengulangi -eopsi: ps -eo pid -eo pcpu -eo commandsama seperti ps -eo pid -o pcpu -o command(apa adanya ps -eo pid,pcpu,command).
  • Ada elseklausa kosong . Itu selalu terlihat seolah-olah harus ditangani, tetapi bukan karena alasan yang tidak diketahui.
Yurim
sumber
2

Mematikan proses yang menggunakan sebagian besar CPU / memori meminta masalah: Lihat saja apa yang ada sekarang di mesin Anda (di sini saat ini firefox, systemd (init), Xorg, gnome-terminal, satu set thread kernel, xemacs; tidak ada yang bisa dibuang). Lihatlah cara men-tweak OOM-killer Linux, misalnya di sini .

Juga perhatikan bahwa "memori yang digunakan oleh proses" adalah konsep samar-samar, karena ada perpustakaan bersama, executable dibagi, dan bahkan bagian dari area data. Satu dapat datang dengan beberapa nomor dengan mengisi setiap pengguna dengan sebagian kecil dari ruang yang digunakan, tetapi bahkan menambahkan bahwa hingga benar-benar tidak memberikan "memori yang digunakan" (bahkan lebih sedikit "memori yang dibebaskan jika prosesnya hilang", bagian yang dibagikan tetap dibelakang).

vonbrand
sumber
1

Saya telah membuat skrip, proses kill , yang membunuh beberapa proses yang terdaftar dalam array, jika penggunaan CPU lebih besar dari XX% untuk YY detik atau membunuh proses yang berjalan lebih dari ZZ detik.

  • Anda dapat mengatur XX, YY, ZZ di bagian atas file.
  • Anda dapat menggunakan ps atau atas untuk proses pemeriksaan.
  • Ada mode lari kering juga, untuk memeriksa tetapi tidak membunuh.
  • Pada akhirnya, skrip mengirim email jika beberapa proses terbunuh.

CATATAN: Ini repo saya di Github: https://github.com/padosoft/kill-process

Berikut screenshotnya:

         ss # 1

Referensi

Bagian penting dari skrip (abstrak kode untuk perintah teratas):

#!/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
Pemakaian:
bash killprocess.sh [dry|kill|--help] [top|ps] [cpu|time]
Lorenzo Padovani
sumber
Sepertinya sortseharusnya begitu sort -k9nr. Tanpa n, akan mendapatkan `5.9`> 29.4.
lk_vc