- Вопрос или проблема
- killall
- pgrep & pkill
- Убийство на основе вашей командной строки
- Идти за друзьями
- Идти за самым молодым другом
- Отображение их имен
- Контроль вывода
- Так как же мне убить процесс с высокой загрузкой CPU?
- Более целенаправленный подход к высокой загрузке CPU
- Ответ или решение
- 1. Использование команды top для определения процесса с высоким CPU
- 2. Скрипт для завершения процесса с высоким использованием CPU
- 3. Настройка скрипта
- 4. Использование регулярных выражений для целевых процессов
- 5. Использование утилит pgrep и pkill
- Заключение
Вопрос или проблема
Иногда программы могут зависать в фоновом режиме и вызывать высокую загрузку процессора. Есть ли способ программно определить, какой процесс в данный момент вызывает наибольшую нагрузку на CPU, и завершить его?
Существует ряд команд Unix, которые, вероятно, лучше подойдут для этого типа работы, если вы их знаете.
- pgrep
- pkill
- killall
Вы можете использовать эти инструменты, чтобы ваши “атаки” были более целенаправленными, особенно в ситуациях, когда вы знаете имя проблемного процесса.
killall
У меня есть повторяющаяся проблема с Chrome, когда его в конечном итоге нужно завершать. Обычно я выполняю эту команду, чтобы eradicate все из них.
$ killall chrome
pgrep & pkill
Но я также могу сделать это, чтобы завершить только самый новый процесс:
# для перечисления
$ pgrep -n chrome
23108
# для завершения
$ pkill -n chrome
Убийство на основе вашей командной строки
Вы также можете добавить переключатель -f
, чтобы достичь тех процессов, которые имеют длинные аргументы пути, на которые вы предпочли бы сослаться, а не только на имя их исполняемого файла.
Например, скажем, у меня есть эти процессы:
$ ps -eaf | grep some
saml 26624 26575 0 22:51 pts/44 00:00:00 some weird command
saml 26673 26624 0 22:51 pts/44 00:00:00 some weird command's friend
saml 26911 26673 8 22:54 pts/44 00:00:00 some weird command's friend
Это просто оболочки Bash с их ARGV0, установленным на эти имена. Кстати, я создал эти процессы, используя этот трюк:
$ (exec -a "some weird command name's friend" bash)
Идти за друзьями
Но допустим, у меня их много, и я хочу пойти только за определенным набором из них, потому что в их командных строках есть “friend”. Я мог бы сделать это:
$ pgrep -f friend
26673
26911
Идти за самым молодым другом
И если их было несколько, и я хотел бы пойти за новым, добавьте переключатель -n
обратно в смесь:
$ pgrep -fn friend
26911
Вы также можете использовать регулярные выражения при использовании переключателя -f
, так что такие команды будут работать, например:
$ pgrep -f "weird.*friend"
26673
26911
Отображение их имен
Вы можете дважды проверить имена процессов с помощью переключателя -l
:
$ pgrep -f "weird.*friend" -l
26673 some weird command's friend
26911 some weird command's friend
Контроль вывода
Или скажите pgrep
, чтобы перечислить идентификаторы процессов, разделенные запятой (,
):
$ pgrep -f "weird.*friend" -d,
26673,26911
Вы можете делать крутые вещи, как это:
$ ps -fp $(pgrep -f weird -d,)
UID PID PPID C STIME TTY TIME CMD
saml 26624 26575 0 22:51 pts/44 00:00:00 some weird command
saml 26673 26624 0 22:51 pts/44 00:00:00 some weird command's friend
saml 26911 26673 0 22:54 pts/44 00:00:00 some weird command's friend
Так как же мне убить процесс с высокой загрузкой CPU?
Я бы использовал вышеуказанные методы, чтобы более избирательно подходить к процессу с высокой загрузкой CPU. Вы можете использовать подход завершения, используя эти методы:
# новейшие парни
$ pkill -nf vlc ; pkill -nf opensnap
# завершить всех этих
$ killall vlc; killall opensnap
Посмотрите на их загрузку CPU:
$ top -b -n 1 | grep -E $(pgrep -f "weird.*friend" -d\|) | grep -v grep
26911 0.1 112m 106m 6408 848 4900 1512 0 0 S 20 0 0.0 some weird command's friend
26673 0.1 112m 106m 6392 848 5020 1504 0 0 S 20 0 0.0 some weird command's friend
Здесь я изменил разделитель с запятой (,
), т.е. этот переключатель -d,
, на вертикальную черту (|
), т.е. этот переключатель -d\|
, чтобы я мог использовать его в grep
. Это вернет идентификаторы процессов так:
$ pgrep -f "weird.*friend" -d\|
26673|26911
Затем мы вставляем их в команду grep -E ...
, чтобы отфильтровать вывод из top
на основе определенных идентификаторов процессов.
Это может показаться слишком сложным, но теперь мы точно знаем, что идентификаторы процессов, которые мы используем, относятся только к определенному процессу с именем “weird.*friend”.
Отсюда вы можете найти процесс с наивысшей загрузкой CPU и завершить его, если действительно хотите пойти этим путем.
Более целенаправленный подход к высокой загрузке CPU
$ top -b -n 1 | grep -E $(pgrep -f "weird.*friend" -d\|) | \
grep -v grep | sort -nk14,14 | tail -1
26911 0.1 112m 106m 6408 848 4900 1512 0 0 S 20 0 0.0 some weird command's friend
Выше показан отсортированный вывод из top
по колонке CPU (14-й). Он отсортирован от наименьшего к наибольшему, поэтому мы берем последнюю строку (tail -1
), которая будет процессом с наивысшей загрузкой CPU среди процессов “weird.*friend”.
Программа “and”, Auto-Nice Daemon может быть настроена на выполнение чего-то подобного.
Вы настраиваете список с несколькими конкретными известными нарушителями и тремя уровнями изменения приоритета (чтобы вы могли постепенно ужесточать изменение приоритета), но любой из которых мог бы быть завершением процесса, хотя это обычно резервируется как последняя мера.
Не всегда легко регулировать вещи так, чтобы достичь определённых уровней загрузки CPU, но есть другие инструменты, которые могут помочь (и помочь избежать завершения нарушающего процесс, предотвращая правонарушение), такие как cpulimit и предварительное запуск программ с nice и ionice.
Отредактированный скрипт
@msw, @sim и другие пользователи подняли обоснованные вопросы относительно концепции моего скрипта. Вдохновленный ответом @sim и замечаниями msw, я сел и пересмотрел, как решить мою конкретную проблему (несколько известных процессов, которые время от времени создают проблемы). Вот что я придумал:
#!/bin/bash
# пытается завершить процесс с наивысшей загрузкой CPU
# (если он является частью указанного списка нарушителей)
TROUBLEMAKERS="vlc opensnap glxgears stress"
sleep 1 # подождите несколько секунд (на всякий случай)
TOPPROCESS=$(top -b -n 1 | sed 1,6d | sed -n 2p)
TOPPID=$(echo "$TOPPROCESS" | awk '{print $1}')
TOPNAME=$(echo "$TOPPROCESS" | awk '{print $12}')
if [[ "$TROUBLEMAKERS" == *"$TOPNAME"* ]]
then
echo "Причина высокой загрузки CPU: "$TOPNAME" ("$TOPPID")"
echo "В списке нарушителей. Завершаем..."
kill -9 $TOPPID
else
echo "Причина высокой загрузки CPU: "$TOPNAME" ("$TOPPID")"
echo "Нет в списке нарушителей. Выход..."
exit 1
fi
exit 0
В отличие от предыдущего скрипта, этот будет завершать процесс с наивысшей загрузкой CPU, только если его имя совпадает с рядом известных нарушителей (процессы, которые склонны зависать в вашей системе).
Оригинальный скрипт
Вот простой скрипт, который определит процесс, вызывающий наивысшую моментальную загрузку CPU в системе и завершит его (за исключением Xorg, который вызовет сбой графического интерфейса):
#!/bin/bash
# пытается завершить процесс с наивысшей загрузкой CPU
# (если это не Xorg)
sleep 1 # подождите несколько секунд (на всякий случай)
TOPPROCESS=$(top -b -n 1 | sed 1,6d | sed -n 2p)
TOPPID=$(echo "$TOPPROCESS" | awk '{print $1}')
TOPNAME=$(echo "$TOPPROCESS" | awk '{print $12}')
if [ "$TOPNAME" != "Xorg" ]
then
kill -9 $TOPPID
else
echo "Загрузка CPU вызвана Xorg. Выход."
exit 1
fi
exit 0
Фрагмент TOPPROCESS
основан на этой записи на commandlinefu.com.
#!/bin/bash
pid=$(ps -eo %cpu,pid --sort -%cpu | head -n 2 | awk '{print $1 " " $2}')
if [[ -n $pid ]]; then
kcpu=$(echo $pid | awk '{print $3}')
kpid=$(echo $pid | awk '{print $4}')
ift=$(echo "90"'<'$kcpu | bc -l)
if [ $ift -eq "0" ]; then
echo "kpid = $kpid"
kill $kpid
fi
else
echo "Не существует"
fi
Совместил предыдущие ответы (для своих целей). Может быть, будет также полезно:
#!/bin/bash
# Убить процессы с загрузкой CPU выше CPU_USAGE_LIMIT.
# (если он является частью указанного списка TROUBLEMAKERS_REGEXP)
TROUBLEMAKERS_REGEXP="^(vlc|opensnap|glxgears|stress)$"
TOP_PROCESSES=10
CPU_USAGE_LIMIT=90
COUNTER=0
IFS=$(echo -en "\n\b")
# Получить TOP_PROCESSES (отсортировать по CPU, исключить заголовок)
for rr in `ps -eo %cpu,pid,comm --sort -%cpu | tail -n +2 | head -n ${TOP_PROCESSES} | awk '{print $1 " " $2 " " $3}'`; do
l_cpu=`echo $rr | awk '{print $1}'`
l_pid=`echo $rr | awk '{print $2}'`
l_command=`echo $rr | awk '{print $3}'`
# сравнить использование CPU процессов с лимитом CPU
result=`echo "${l_cpu} >= ${CPU_USAGE_LIMIT}" | bc -l`
if [[ "${result}" = "1" ]]; then
echo "${l_command}: Найден PID [${l_pid}] с использованием CPU [${l_cpu}] > ${CPU_USAGE_LIMIT}%"
# Он в списке?
if [[ "${l_command}" =~ ${TROUBLEMAKERS_REGEXP} ]];then
echo "${l_command}: Завершаем PID [${l_pid}]."
kill ${l_pid}
else
echo "${l_command}: Пропущен PID [${l_pid}]."
fi
else
# первый процесс с использованием CPU < лимита CPU => разорвать цикл
if [[ $COUNTER -eq 0 ]];then
echo "Нет процессов с использованием CPU ограниченным [${CPU_USAGE_LIMIT}]."
else
echo "Нет больше процессов с использованием CPU ограниченным [${CPU_USAGE_LIMIT}]."
fi
break;
fi
COUNTER=$((COUNTER + 1))
done
Ответ или решение
Автоматическое завершение процессов с высоким загрузкой CPU является важной задачей для поддержания производительности системы. В данной инструкции мы рассмотрим, как это сделать на Unix-системах с использованием команд top
, ps
, kill
и других утилит.
1. Использование команды top
для определения процесса с высоким CPU
Команда top
позволяет мониторить активные процессы и их использование ресурсов в реальном времени. Для автоматизации этого процесса вы можете использовать команду top
вместе с другими инструментами.
2. Скрипт для завершения процесса с высоким использованием CPU
Вы можете создать простой скрипт на Bash, который будет определять и завершать процесс с максимальной загрузкой CPU. Вот пример такого скрипта:
#!/bin/bash
# Установка предела загрузки CPU
CPU_USAGE_LIMIT=90
# Получение информации о процессе с самой высокой загрузкой CPU
TOPPROCESS=$(ps -eo %cpu,pid,comm --sort=-%cpu | sed -n '2p')
TOPCPU=$(echo "$TOPPROCESS" | awk '{print $1}')
TOPPID=$(echo "$TOPPROCESS" | awk '{print $2}')
TOPNAME=$(echo "$TOPPROCESS" | awk '{print $3}')
# Проверка, превысила ли загрузка CPU установленный предел
if (( $(echo "$TOPCPU > $CPU_USAGE_LIMIT" | bc -l) )); then
echo "Процесс: $TOPNAME (PID: $TOPPID) использует $TOPCPU% CPU, превышая лимит."
# Завершение процесса
kill -9 $TOPPID
echo "Процесс $TOPNAME с PID $TOPPID был завершен."
else
echo "На данный момент нет процессов с загрузкой выше $CPU_USAGE_LIMIT%."
fi
3. Настройка скрипта
- Создайте файл с расширением
.sh
, напримерkill_high_cpu.sh
, и вставьте в него указанный выше код. - Дайте права на исполнение скрипта:
chmod +x kill_high_cpu.sh
- Запускайте скрипт периодически (например, через cron) для автоматического мониторинга.
4. Использование регулярных выражений для целевых процессов
Если вы хотите завершать только определенные "проблемные" процессы, можно добавить проверку на наличие их имен в списке. Вот измененный вариант скрипта:
#!/bin/bash
# Список процессов, которые нужно завершать
TROUBLEMAKERS="vlc opensnap glxgears stress"
# Установка предела загрузки CPU
CPU_USAGE_LIMIT=90
# Получение информации о процессе с самой высокой загрузкой CPU
TOPPROCESS=$(ps -eo %cpu,pid,comm --sort=-%cpu | sed -n '2p')
TOPCPU=$(echo "$TOPPROCESS" | awk '{print $1}')
TOPPID=$(echo "$TOPPROCESS" | awk '{print $2}')
TOPNAME=$(echo "$TOPPROCESS" | awk '{print $3}')
if (( $(echo "$TOPCPU > $CPU_USAGE_LIMIT" | bc -l) )); then
echo "Процесс: $TOPNAME (PID: $TOPPID) использует $TOPCPU% CPU, превышая лимит."
if [[ "$TROUBLEMAKERS" == *"$TOPNAME"* ]]; then
kill -9 $TOPPID
echo "Процесс $TOPNAME с PID $TOPPID был завершен."
else
echo "$TOPNAME не входит в список проблемных процессов. Завершение отменено."
fi
else
echo "На данный момент нет процессов с загрузкой выше $CPU_USAGE_LIMIT%."
fi
5. Использование утилит pgrep
и pkill
Если вы знаете группы процессов, которые вероятно могут использовать высокий CPU, вы можете использовать pgrep
и pkill
для завершения всех процессов с определенным именем, например:
pkill -f "имя_процесса"
Заключение
Создание автоматического механизма для завершения процессов с высокой загрузкой CPU может существенно улучшить производительность вашей системы. Настраивая параметры и добавляя специфические условия для нужд вашей системы, вы можете более эффективно управлять ресурсами.