Сценарій Bash, який автоматично вбиває процеси, коли використання процесора / пам'яті стає занадто високим


11

Я створив сценарій, який вбиває процеси, якщо використання процесора та / або пам'яті досягає 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
Перший понеділок місяця, і мій ПК перевіряє (slow'ish) набір RAID6. Завантаження процесора легко досягає вище 8, оскільки він постійно чекає дискового вводу з цього набору RAID. Нічого поганого, система все ще дуже чуйна. Ваш сценарій убив би мою Firefox, яка використовує лише 3,6% з 400% доступних. Просто кажучи, що ви можете полювати за привидами за допомогою цього сценарію. BTW: ваша система не пошкодиться через велике навантаження, і коли пам’ять вичерпається, ядро ​​зробить напівосвічену здогадку, який процес (и) вбити.
jippie

Тоді процес вбивства на основі завантаження буде нормальним чи ні ????
Кетан Патель

У моєму випадку використання вбивство не бажане.
jippie

Відповіді:


11

Я здогадуюсь, що проблема, яку ви хочете вирішити, полягає в тому, що у вашій коробці працює якийсь процес, який іноді погано поводиться, і сидить назавжди, прив’язуючи ядро.

Перше, що ви хочете зробити, - це спробувати виправити програму, яка зійшла з розуму. Це, безумовно, найкраще рішення. Я припускаю, що це неможливо, або вам потрібен швидкий клубок, щоб тримати вашу коробку до фіксації.

Ви, як мінімум, хочете обмежити свій сценарій, щоб потрапити лише на ту програму, яка вас хвилює. Було б найкраще, якби дозволи обмежили ваш сценарій так (наприклад, ваш сценарій працює як користувач X, єдине інше, що працює як X - програма).

Ще краще було б використовувати щось на кшталт ulimit -tобмеження кількості загального процесорного часу, який може використовувати програма. Аналогічно, якщо вона споживає всю пам'ять, перевірте ulimit -v. Ядро виконує ці обмеження; Докладні відомості див. у bashманпайті (це вбудована оболонка) та setrlimit(2)вручну.

Якщо проблема не є процесом запуску amok, а замість цього запущено занадто багато процесів, то застосуйте певну форму блокування, щоб запобігти запуску більш ніж X (або - це має бути знайоме - ulimit -u). Ви можете також розглянути можливість зміни пріоритету планувальника цих процесів (з використанням niceабо renice) або для ще більш різкого використання sched_setschedulerдля зміни політики на SCHED_IDLE.

Якщо вам потрібно ще більше контролю, подивіться контрольні групи (групи). Залежно від ядра, яке ви працюєте, ви можете фактично обмежити кількість часу процесора, пам'яті, вводу / виводу тощо, яке споживає ціла група процесів разом. Контрольні групи досить гнучкі; вони, ймовірно, можуть робити все, що ви намагаєтесь зробити, без крихких клубочків. Arch Linux Wiki має вступ до груп, який варто прочитати, як і серія груп груп Ніла Брауна на LWN.


3

Проблеми:

  • При сортуванні числових полів , які ви , ймовірно , хочете використовувати -nопцію: sort -nrk 2. Інакше рядок зі %CPUзначенням 5,0 у кінцевому підсумку буде вище, ніж один зі значенням 12,0.
  • Залежно від вашої psреалізації, ви можете скористатися --no-headersопцією для позбавлення від grep -v. Це заважає вам відкидати команди, які містять PID.
  • Я здогадуюсь замість echo CPU USAGE is at $CPU_LOAD, ви мали на увазі echo 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

Вбивство процесів, які використовують більшість процесорів / пам'яті, викликає проблеми: просто подивіться, що вони зараз є на вашій машині (тут зараз Firefox, systemd (init), Xorg, gnome-terminal, набір ниток ядра, xemacs; жоден з яких не є необхідним). Подивіться, як налаштувати Linux-вбивцю OOM, наприклад, тут .

Також зауважте, що "пам'ять, яка використовується процесом", є неяскравою концепцією, оскільки є спільні бібліотеки, спільні файли спільного доступу та навіть частини областей даних. Можна придумати деяку кількість, заряджаючи кожного користувача частиною використовуваного простору, але навіть додаючи, що вгору справді не дається "пам'ять, що використовується" (ще менше "пам'ять звільнена, якщо процес піде", частини розділяються позаду).


1

Я створив скрипт, kill-process , який вбиває деякі процеси, перелічені в масиві, якщо використання процесора перевищує XX% протягом YY секунд або вбиває процеси, що працюють більше ZZ секунд.

  • Ви можете встановити XX, YY, ZZ у верхній частині файлу.
  • Ви можете використовувати ps або top для процесів перевірки.
  • Існує і режим сухого запуску, щоб перевірити, але не вбити.
  • Врешті-решт, сценарій надсилає електронне повідомлення, якщо деякі процеси були вбиті.

ПРИМІТКА. Ось мій репо в Github: https://github.com/padosoft/kill-process

Ось скріншот:

         ss №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цього вийде `5.9`> 29.4.
lk_vc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.