Скрипт 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в сценарии работают постоянно? Это дает мне озноб ...
Рахму
1
Хороший аватар в любом случае, @rahmu он получил sleep 1в петле
маргаритка
1
Первый понедельник месяца, и мой компьютер проверяет (медленный) набор RAID6. Загрузка процессора легко достигает пика выше 8, потому что он постоянно ожидает дискового ввода-вывода из этого набора RAID. Ничего плохого, система все еще очень отзывчива. Ваш скрипт убьет мой Firefox, который использует только 3,6% из доступных 400%. Просто сказать, что вы можете охотиться на призраков с помощью этого сценария. Кстати: ваша система не будет повреждена из-за высокой нагрузки, и когда память закончится, ядро ​​сделает полуобученное предположение, какой процесс (ы) убить.
Джиппи
Тогда убить процесс на основе загрузки будет нормально или нет ????
Кетан Патель
В моем случае убийство нежелательно.
Джиппи

Ответы:

11

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

Первое, что вы хотите сделать, это попытаться исправить сумасшедшую программу. Это, безусловно, лучшее решение. Я собираюсь предположить, что это невозможно, или вам нужен быстрый Kluge, чтобы ваш ящик работал до тех пор, пока он не будет исправлен.

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

Еще лучше было бы использовать что-то вроде ulimit -tограничения общего времени процессора, которое может использовать программа. Точно так же, если он потребляет всю память, проверьте ulimit -v. Ядро применяет эти ограничения; смотрите bashman-страницу (это встроенная оболочка) и setrlimit(2)man-страницу для подробностей.

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

Если вам нужно еще больше контроля, взгляните на контрольные группы (cgroups). В зависимости от того, какое ядро ​​вы используете, вы можете на самом деле ограничить количество процессорного времени, памяти, ввода-вывода и т. Д., Которое потребляет целая группа процессов. Контрольные группы довольно гибки; скорее всего, они могут делать все, что вы пытаетесь, без каких-либо хрупких клугов. Arch Linux Wiki имеет введение в cgroups, которое стоит прочитать, как и серия cgroups Нила Брауна на LWN.

derobert
источник
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предложение. Это всегда выглядит так, как будто это должно быть обработано, но не по какой-то неизвестной причине.
Yurim
источник
2

Убийство процессов, которые используют большую часть ресурсов процессора / памяти, вызывает проблемы: просто посмотрите, какие они сейчас на вашем компьютере (здесь в настоящее время firefox, systemd (init), Xorg, gnome-терминал, набор потоков ядра, xemacs; ни один из которых не является обязательным). Посмотрите, как настроить OOM-убийцу в Linux, например, здесь .

Также обратите внимание, что «память, используемая процессом» является туманным понятием, поскольку существуют общие библиотеки, общие исполняемые файлы и даже части областей данных. Можно придумать какое-то число, взимая с каждого пользователя часть использованного пространства, но даже если добавить, что это действительно не дает «использованной памяти» (еще меньше «освобождается память, если процесс уходит»), разделяемые части остаются позади).

vonbrand
источник
1

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

  • Вы можете установить XX, YY, ZZ в верхней части файла.
  • Вы можете использовать ps или top для проверки процессов.
  • Также есть режим пробного запуска, чтобы проверить, но не убить.
  • В конце сценарий отправляет электронное письмо, если некоторые процессы были убиты.

ПРИМЕЧАНИЕ. Вот мой репозиторий на 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, получим `5.9`> 29.4.
lk_vc