Script di Bash che uccide automaticamente i processi quando l'utilizzo della CPU / memoria diventa troppo elevato


11

Ho creato uno script che uccide i processi se l'utilizzo della CPU e / o della memoria raggiunge l'80%. Crea un elenco di processi interrotti quando ciò accade. Cosa posso fare per migliorarlo?

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
Hai provato a eseguire lo script? while [ 1 ]mi chiedo quanta CPU consumerà solo questo script. Inoltre, 3 chiamate a kill -9in uno script sono in esecuzione costantemente? Questo mi dà i brividi ...
Rahmu

1
Bel avatar comunque, @rahmu ha ottenuto un sleep 1in the loop
daisy

1
Primo lunedì del mese e il mio PC sta controllando un set RAID6 (lento). Il carico della CPU supera facilmente l'8 perché è costantemente in attesa di IO del disco da questo set RAID. Niente di male, il sistema è ancora molto reattivo. Il tuo script ucciderebbe il mio Firefox che utilizza solo il 3,6% del 400% disponibile. Dico solo che potresti essere alla ricerca di fantasmi con questa sceneggiatura. A proposito: il tuo sistema non verrà danneggiato a causa dell'elevato carico e quando la memoria si esaurisce, il kernel farà un'ipotesi semi-istruita su quale processo (i) uccidere.
jippie,

Quindi il processo di kill sul caricamento basato andrà bene o no ????
Ketan Patel,

Nel mio caso d'uso l'uccisione non è desiderata.
jippie

Risposte:


11

Sto indovinando il problema che si vuole risolvere è che hai qualche processo in esecuzione sulla propria macchina che a volte si comporta male, e si siede per sempre agganciare un nucleo.

La prima cosa che vuoi fare è tentare di riparare il programma che impazzisce. Questa è di gran lunga la soluzione migliore. Presumo che non sia possibile, o hai bisogno di un veloce kluge per mantenere la tua scatola in esecuzione fino a quando non viene risolto.

Almeno, vuoi limitare il tuo script per colpire solo il programma di cui ti preoccupi. Sarebbe meglio se le autorizzazioni limitassero lo script in questo modo (ad esempio, lo script viene eseguito come utente X, l'unica altra cosa in esecuzione come X è il programma).

Ancora meglio sarebbe usare qualcosa di simile ulimit -tper limitare la quantità di tempo totale della CPU che il programma può usare. Allo stesso modo, se consuma tutta la memoria, controlla ulimit -v. Il kernel applica questi limiti; vedere la bashmanpage (è una shell integrata) e la setrlimit(2)manpage per i dettagli.

Se il problema non è un processo in esecuzione, ma è invece solo un numero eccessivo di processi in esecuzione, implementare una qualche forma di blocco per impedire l'esecuzione di più di X (o — questo dovrebbe essere familiare— ulimit -u). Si può anche considerare di cambiare la priorità dello scheduler di quei processi (usando niceo renice), o per ancora più drastica, usando sched_setschedulerper cambiare la politica in SCHED_IDLE.

Se hai bisogno di un controllo ancora maggiore, dai un'occhiata a gruppi di controllo (cgroups). A seconda del kernel che stai eseguendo, puoi effettivamente limitare la quantità di tempo della CPU, memoria, I / O, ecc. Che consumano insieme un intero gruppo di processi. I gruppi di controllo sono abbastanza flessibili; possono probabilmente fare qualunque cosa tu stia cercando di fare, senza fragili kluges. Arch Linux Wiki ha un'introduzione ai cgroups che vale la pena leggere, così come la serie di cgroups di Neil Brown su LWN.


3

Problemi:

  • Quando si ordina campi numerici probabilmente si desidera utilizzare l' -nopzione di: sort -nrk 2. Altrimenti una linea con un %CPUvalore di 5.0 finirà per essere superiore a una con un valore di 12,0.
  • A seconda della tua psimplementazione potresti voler usare l' --no-headersopzione per sbarazzarti di grep -v. Ciò ti impedisce di scartare i comandi che contiene PID.
  • Immagino invece di echo CPU USAGE is at $CPU_LOAD, volevi dire echo CPU USAGE is at $CPU_USAGE.
  • Immagino che hai dimenticato di rimuovere quello exit 0che hai inserito durante il debug (?).

Stile:

  • Potresti voler spostare la CPU_USAGE_THRESHOLD=800riga all'inizio del file, poiché questa è la cosa più informativa ed è molto probabile che venga cambiata anche dopo che lo script è stabile.
  • Stai ripetendo l' -eopzione: ps -eo pid -eo pcpu -eo commandè uguale a ps -eo pid -o pcpu -o command(così com'è ps -eo pid,pcpu,command).
  • C'è una elseclausola vuota . Sembra sempre che debba essere gestito, ma non è stato per qualche motivo sconosciuto.

2

Uccidere i processi che utilizzano la maggior parte della CPU / memoria richiede problemi: basta guardare a quello che sono in questo momento sulla tua macchina (qui attualmente Firefox, Systemd (Init), Xorg, gnome-terminal, un insieme di thread del kernel, xemacs; nessuno dei quali è superfluo). Guarda come modificare OOM-killer di Linux, ad esempio qui .

Si noti inoltre che "la memoria utilizzata dal processo" è un concetto nebuloso, in quanto vi sono librerie condivise, file eseguibili condivisi e persino parti di aree dati. Si può trovare un certo numero caricando ogni utente con una frazione dello spazio utilizzato, ma anche aggiungendo che in realtà non si ottiene "memoria utilizzata" (ancor meno "memoria liberata se il processo va via", le parti condivise rimangono dietro a).


1

Ho creato uno script, kill-process , che uccide alcuni processi elencati in un array, se l'utilizzo della CPU è maggiore del XX% per YY secondi o uccide i processi che eseguono più di ZZ secondi.

  • È possibile impostare XX, YY, ZZ nella parte superiore del file.
  • Puoi usare ps o top per i processi di controllo.
  • C'è anche una modalità di funzionamento a secco, per controllare ma non uccidere.
  • Alla fine, lo script invia un'e-mail se alcuni processi sono stati interrotti.

NOTA: ecco il mio repository su Github: https://github.com/padosoft/kill-process

Ecco uno screenshot:

         ss # 1

Riferimenti

Parte essenziale dello script (un estratto del codice per il comando principale):

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

Sembra che sortdovrebbe essere sort -k9nr. Senza n, otterrà `5.9`> 29.4.
lk_vc
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.