CPU / bellek kullanımı çok yükseldiğinde süreçleri otomatik olarak öldüren Bash betiği


11

CPU ve / veya bellek kullanımı% 80'e ulaştığında işlemleri öldüren bir komut dosyası oluşturdum. Bu gerçekleştiğinde öldürülen süreçlerin bir listesini oluşturur. Geliştirmek için ne yapabilirim?

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
Senaryoyu çalıştırmayı denedin mi? while [ 1 ]Bu komut dosyasının tek başına ne kadar CPU harcayacağını merak ediyor. Ayrıca, kill -9sürekli çalışan bir script 3 çağrı ? Bu bana titreme veriyor ...
rahmu

1
Yine de güzel avatar, @rahmu sleep 1döngüde bir var
papatya

1
Ayın ilk Pazartesi günü ve bilgisayarım (yavaş) RAID6 setini kontrol ediyor. CPU yükü kolayca 8'in üzerine çıkar çünkü sürekli olarak bu RAID setinden disk IO'yu bekler. Yanlış bir şey yok, sistem hala çok duyarlı. Betiğiniz, mevcut% 400'ün yalnızca% 3,6'sını kullanan firefox'umu öldürecekti. Sadece bu senaryo ile hayaletler avlıyor olabilirsiniz. BTW: Sisteminiz yüksek yük nedeniyle hasar görmeyecek ve bellek bittiğinde, çekirdek hangi işlem (ler) i öldürmek için yarı eğitimli bir tahmin yapacak.
jippie

Sonra dayalı yük öldürme işlemi iyi ya da değil olacak ????
Ketan Patel

Benim kullanımım durumunda öldürme istenmiyor.
jippie

Yanıtlar:


11

Çözmek istediğiniz problemin, kutunuzda bazen yanlış davranan ve sonsuza dek bir çekirdeği sabitleyen bir işleminiz olduğu tahmin ediyorum .

Yapmak istediğiniz ilk şey, çıldırmış olan programı düzeltmeye çalışmaktır. Bu en iyi çözüm. Bunun mümkün olmadığını varsayacağım, ya da kutunuzu tamir edene kadar hızlı bir şekilde çalışmanız gerekiyor.

En azından, senaryonuzu sadece endişe duyduğunuz bir programa çarpacak şekilde sınırlamak istiyorsunuz. İzinlerin komut dosyanızı böyle sınırlaması en iyisi olacaktır (örneğin, komut dosyanız X kullanıcısı olarak çalışır, X olarak çalışan tek şey programdır).

Daha da iyisi ulimit -t, programın kullanabileceği toplam CPU süresini sınırlamak gibi bir şey kullanmak olabilir. Benzer şekilde, tüm belleği tüketiyorsa, kontrol edin ulimit -v. Çekirdek bu sınırları uygular; ayrıntılar için bashmanpage (yerleşik bir kabuk) ve setrlimit(2)manpage'e bakın.

Sorun amok çalışan bir işlem değilse, bunun yerine çok fazla işlem çalışıyorsa, X'ten daha fazlasının çalışmasını önlemek için bir tür kilitleme uygulayın (veya —Bu tanıdık olmalıdır- ulimit -u). Ayrıca, bu işlemlerin zamanlayıcı önceliğini ( niceveya kullanarak renice) sched_setschedulerdeğiştirmeyi veya daha da kesin olarak, ilkeyi değiştirmek için kullanarak da düşünebilirsiniz SCHED_IDLE.

Daha fazla kontrole ihtiyacınız varsa, kontrol gruplarına (cgroups) bir göz atın. Çalıştırdığınız çekirdeğe bağlı olarak, tüm süreç grubunun birlikte tükettiği CPU süresi, bellek, G / Ç, vb. Miktarını sınırlayabilirsiniz. Kontrol grupları oldukça esnektir; muhtemelen herhangi bir kırılgan ipucu olmadan yapmaya çalıştığınız her şeyi yapabilirler. Arch Linux Wiki'nin , Neil Brown'ın LWN'deki cgroups serisi gibi okumaya değer gruplara bir girişi var .


3

Sorunlar:

  • Sayısal alanları sıralarken muhtemelen -n: seçeneğini kullanmak istersiniz sort -nrk 2. Aksi takdirde %CPU, 5.0 değerine sahip bir satır , 12.0 değerine sahip bir satırdan daha yüksek olacak.
  • Uygulamanıza bağlı olarak, kurtulmak psiçin --no-headersseçeneğini kullanabilirsiniz grep -v. Bu, içerdiği komutları atmanızı önler PID.
  • Sanırım bunun yerine echo CPU USAGE is at $CPU_LOAD, demek istedin echo CPU USAGE is at $CPU_USAGE.
  • exit 0Hata ayıklama (?) Sırasında eklediğiniz kaldırmayı unuttum sanırım .

Stil:

  • CPU_USAGE_THRESHOLD=800Satırı dosyanın başlangıcına taşımak isteyebilirsiniz , çünkü bu en bilgilendirici şeydir ve komut dosyanız sabitlendikten sonra bile büyük olasılıkla değişecektir.
  • Sen tekrarlıyorsun -eseçeneği: ps -eo pid -eo pcpu -eo commandaynıdır ps -eo pid -o pcpu -o command(olduğu gibi ps -eo pid,pcpu,command).
  • Boş bir elsemadde var. Bu her zaman ele alınması gerektiği gibi görünür, ancak bilinmeyen bir nedenden ötürü değildi.

2

Çoğu CPU / bellek kullanan işlemleri öldürmek sorun istiyor: Sadece şu anda makinenizde ne olduklarına bakın (şu anda firefox, systemd (init), Xorg, gnome-terminal, bir dizi çekirdek iş parçacığı, xemacs; hiçbiri dağıtılamaz). Linux'un OOM-katilini nasıl değiştireceğinize bakın, örneğin burada .

Ayrıca, paylaşılan işlem kütüphaneleri, yürütülebilir dosyalar paylaşıldığı ve hatta veri alanlarının bir kısmı olduğu için "işlem tarafından kullanılan bellek" nebuz bir kavramdır. Her kullanıcıya kullanılan alanın bir kısmını şarj ederek bir miktar gelebilir, ancak bunu eklemenin bile "kullanılan bellek" (işlem kaybolursa daha az "bellek serbest bırakılmadığını" eklemesi parçalar paylaşır arkasında).


1

CPU kullanımı YY saniye için% XX'den büyükse veya ZZ saniyeden fazla çalışan işlemleri öldürürse, bir dizide listelenen bazı işlemleri öldüren bir komut dosyası, kill işlemi oluşturdum .

  • Dosyanın üst kısmında XX, YY, ZZ'yi ayarlayabilirsiniz.
  • Kontrol işlemleri için bir ps veya üstü kullanabilirsiniz.
  • Kontrol etmek ama öldürmek için kuru çalışma modu da var.
  • Sonunda, bazı süreçler öldürüldüğünde komut dosyası bir e-posta gönderir.

NOT: İşte Github'daki repo'm: https://github.com/padosoft/kill-process

İşte bir ekran görüntüsü:

         ss 1.

Referanslar

Betiğin önemli kısmı (üst komut için bir kod özeti):

#!/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
Kullanımı:
bash killprocess.sh [dry|kill|--help] [top|ps] [cpu|time]

Görünen sorto ki sort -k9nr. Olmadan n, `` 5.9 '' alacaksınız 29.4.
lk_vc
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.