Ограничение определенных процессов до% процессора - Linux - PullRequest
30 голосов
/ 22 декабря 2008

У меня следующая проблема: некоторые процессы, генерируемые динамически, имеют тенденцию к потреблению 100% ресурсов ЦП. Я хотел бы ограничить весь процесс, соответствующий какому-либо критерию (например, имя процесса), до определенного процента загрузки процессора.

Конкретная проблема, которую я пытаюсь решить, заключается в использовании процессов свёртывания @ домашнего работника. Лучшее решение, о котором я могу подумать, - это Perl-скрипт, который выполняется периодически и использует утилиту cpulimit для ограничения процессов (если вас интересует более подробная информация, посмотрите этот пост в блоге ). Это работает, но это взломать: /

Есть идеи? Я хотел бы оставить обработку процессов для ОС :)


Еще раз спасибо за предложения, но мы все еще не достигли цели:)

Решение "slowDown" - это, по сути, утилита "cpulimit". Мне все еще нужно позаботиться о том, какие процессы замедлить, убить процесс «slowDown» после завершения рабочего процесса и запустить новые для новых рабочих процессов. Это именно то, что я сделал со скриптом Perl и работой cron.

Основная проблема в том, что я заранее не знаю, какие процессы ограничивать. Они генерируются динамически.

Может быть, есть способ ограничить все процессы одного пользователя определенным количеством процессорного процента? Я уже настроил пользователя для выполнения заданий fold @ home, надеясь, что смогу ограничить его файлом /etc/security/limits.conf. Но самое близкое, что я мог получить - это общее время процессора на пользователя ...

Было бы здорово, если бы было что-то, что позволило бы вам сказать: Msgstr "Сумма использования ЦП всех процессов этого пользователя не может превышать 50%". А потом пусть процессы борются за эти 50% процессоров в соответствии с их приоритетами ...


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

Я бы просто хотел, чтобы процессор не работал на 100% в течение продолжительных периодов ...

Ответы [ 15 ]

21 голосов
/ 14 декабря 2011

У меня была слегка похожая проблема с gzip.

Предполагая, что мы хотим уменьшить ЦП процесса gzip:

    gzip backup.tar & sleep 2 & cpulimit --limit 10 -e gzip -z

Параметры:

  • Я нашел sleep полезным, поскольку cpulimit иногда не сразу запускал новый gzip процесс
  • --limit 10 ограничивает gzip загрузка ЦП до 10%
  • -z автоматически закрывается cpulimit, когда gzip процесс завершается

Другой вариант - запустить демон cpulimit.

13 голосов
/ 23 декабря 2008

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

loop
    wait for some time tR
    send SIGSTOP to the process you want to be scheduled
    wait for some time tP
    send SIGCONT to the process.
loopEnd

соотношение tR / tP контролирует загрузку процессора.


Вот небольшое доказательство концепции. «Занят» - это программа, которая использует ваше процессорное время и которую вы хотите замедлить с помощью «slowDown»:

> cat > busy.c:
    main() { while (1) {}; }

> cc -o busy busy.c
> busy &
> top

Tasks: 192 total,   3 running, 189 sleeping,   0 stopped,   0 zombie
Cpu(s): 76.9% us,  6.6% sy,  0.0% ni, 11.9% id,  4.5% wa,  0.0% hi,  0.0% si
Mem:   6139696k total,  6114488k used,    25208k free,   115760k buffers
Swap:  9765368k total,  1606096k used,  8159272k free,  2620712k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
26539 cg        25   0  2416  292  220 R 90.0  0.0   3:25.79 busy
...

> cat > slowDown
while true; do
 kill -s SIGSTOP $1
 sleep 0.1
 kill -s SIGCONT $1
 sleep 0.1
done

> chmod +x slowDown
> slowDown 26539 &
> top
Tasks: 200 total,   4 running, 192 sleeping,   4 stopped,   0 zombie
Cpu(s): 48.5% us, 19.4% sy,  0.0% ni, 20.2% id,  9.8% wa,  0.2% hi,  2.0% si
Mem:   6139696k total,  6115376k used,    24320k free,    96676k buffers
Swap:  9765368k total,  1606096k used,  8159272k free,  2639796k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
26539 cg        16   0  2416  292  220 T 49.7  0.0   6:00.98 busy
...

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

С уважением

7 голосов
/ 17 апреля 2012

Я думаю, что в Linux нет решения ограничить использование процессора, но есть приемлемый способ ограничить любой процесс определенным использованием процессора: http://ubuntuforums.org/showthread.php?t=992706

В случае, если они удаляют информацию, вот снова


  1. УСТАНОВИТЬ ПАКЕТЫ

  2. Установить пакет cpulimit. Код:

    sudo apt-get install cpulimit

  3. Установить пакет gawk. Код:

    sudo apt-get install gawk

  4. СОЗДАТЬ ДЕМОННЫЙ ФАЙЛ CPULIMIT

Откройте текстовый редактор с правами суперпользователя и сохраните приведенный ниже текст скрипта демона в новый файл /usr/bin/cpulimit_daemon.sh

Код:

#!/bin/bash
# ==============================================================
# CPU limit daemon - set PID's max. percentage CPU consumptions
# ==============================================================

# Variables
CPU_LIMIT=20        # Maximum percentage CPU consumption by each PID
DAEMON_INTERVAL=3   # Daemon check interval in seconds
BLACK_PROCESSES_LIST=   # Limit only processes defined in this variable. If variable is empty (default) all violating processes are limited.
WHITE_PROCESSES_LIST=   # Limit all processes except processes defined in this variable. If variable is empty (default) all violating processes are limited.

# Check if one of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST is defined.
if [[ -n "$BLACK_PROCESSES_LIST" &&  -n "$WHITE_PROCESSES_LIST" ]] ; then    # If both variables are defined then error is produced.
   echo "At least one or both of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST must be empty."
   exit 1
elif [[ -n "$BLACK_PROCESSES_LIST" ]] ; then                                 # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
   NEW_PIDS_COMMAND="top -b -n1 -c | grep -E '$BLACK_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
elif [[ -n "$WHITE_PROCESSES_LIST" ]] ; then                                 # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
   NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6' | grep -E -v '$WHITE_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
else
   NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6 && \$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
fi

# Search and limit violating PIDs
while sleep $DAEMON_INTERVAL
do
   NEW_PIDS=$(eval "$NEW_PIDS_COMMAND")                                                                    # Violating PIDs
   LIMITED_PIDS=$(ps -eo args | gawk '$1=="cpulimit" {print $3}')                                          # Already limited PIDs
   QUEUE_PIDS=$(comm -23 <(echo "$NEW_PIDS" | sort -u) <(echo "$LIMITED_PIDS" | sort -u) | grep -v '^$')   # PIDs in queue

   for i in $QUEUE_PIDS
   do
       cpulimit -p $i -l $CPU_LIMIT -z &   # Limit new violating processes
   done
done
  1. ИЗМЕНИТЬ ПЕРЕМЕННЫЕ ДЛЯ ВАШЕЙ СРЕДЫ ТРЕБУЕТСЯ

CPU_LIMIT Измените эту переменную в приведенном выше сценарии, если вы хотите, чтобы потребление ЦП для каждого процесса не превышало 20%. Пожалуйста, прочитайте главу «При использовании компьютера SMP» ниже, если у вас есть компьютер SMP (более 1 ЦП или ЦП с более чем 1 ядром).

DAEMON_INTERVAL Измените эту переменную в приведенном выше скрипте, если вы хотите проводить более / менее регулярную проверку Интервал указывается в секундах, а по умолчанию установлено значение 3 секунды.

BLACK_PROCESS_LIST и WHITE_PROCESSES_LIST Переменная BLACK_PROCESSES_LIST ограничивает только указанные процессы. Если переменная пуста (по умолчанию), все нарушающие процессы ограничены.

Переменная WHITE_PROCESSES_LIST ограничивает все процессы, кроме процессов, определенных в этой переменной. Если переменная пуста (по умолчанию), все нарушающие процессы ограничены.

Одна или обе переменные BLACK_PROCESSES_LIST и WHITE_PROCESSES_LIST должны быть пустыми - не логично, что обе переменные определены.

Вы можете указать несколько процессов в одной из этих двух переменных, используя символы разделителя "|" (без двойных кавычек). Пример: если вы хотите cpulimit для всех процессов кроме процессов mysql, firefox и gedit, установите переменную: WHITE_PROCESSES_LIST = "mysql | firefox | gedit"

  1. ПРОЦЕДУРА АВТОМАТИЧЕСКОГО ЗАПУСКА ДЕМОНА В ЗАГРУЗКУ

  2. Установка прав доступа для пользователя root: Код:

    sudo chmod 755 /usr/bin/cpulimit_daemon.sh

  3. Открыть текстовый редактор с привилегиями root и сохранить приведенный ниже скрипт в новый файл /etc/init.d/cpulimit

Код:

#!/bin/sh
#
# Script to start CPU limit daemon
#
set -e

case "$1" in
start)
if [ $(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print $1}' | wc -l) -eq 0 ]; then
    nohup /usr/bin/cpulimit_daemon.sh >/dev/null 2>&1 &
    ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon started successfully"; else print " * cpulimit daemon can not be started" }'
else
    echo " * cpulimit daemon can't be started, because it is already running"
fi
;;
stop)
CPULIMIT_DAEMON=$(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print $1}' | wc -l)
CPULIMIT_INSTANCE=$(ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | wc -l)
CPULIMIT_ALL=$((CPULIMIT_DAEMON + CPULIMIT_INSTANCE))
if [ $CPULIMIT_ALL -gt 0 ]; then
    if [ $CPULIMIT_DAEMON -gt 0 ]; then
        ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print $1}' | xargs kill -9   # kill cpulimit daemon
    fi

    if [ $CPULIMIT_INSTANCE -gt 0 ]; then
        ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | xargs kill -9                    # release cpulimited process to normal priority
    fi
    ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon can not be stopped"; else print " * cpulimit daemon stopped successfully" }'
else
    echo " * cpulimit daemon can't be stopped, because it is not running"
fi
;;
restart)
$0 stop
sleep 3
$0 start
;;
status)
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon is running"; else print " * cpulimit daemon is not running" }'
;;
esac
exit 0
  1. Смена владельца файла на root:

Код:

sudo chown root:root /etc/init.d/cpulimit
  1. Изменение прав доступа:

Код:

sudo chmod 755 /etc/init.d/cpulimit
  1. Добавить скрипт в каталоги процедур загрузки: Код:

    sudo update-rc.d cpulimit по умолчанию

  2. Перезагрузитесь, чтобы проверить, запускает ли скрипт демон cpulimit во время загрузки: Код:

    перезагрузка sudo

  3. РУЧНАЯ ПРОВЕРКА, ОСТАНОВКА, ЗАПУСК И ПЕРЕЗАПУСК DAEMON

Примечание. Демон и служба в этом руководстве имеют одинаковое значение.

Примечание: Для пользователей, использующих Ubuntu 8.10 (например, Ubuntu 8.04 LTS) вместо служебной команды, используйте синтаксис "sudo /etc/init.d/cpulimit status / start / stop / restart" или установите пакет sysvconfig с помощью команды: sudo apt-get установить sysvconfig

Проверьте, запущена ли служба cpulimit Команда проверки возвращает: «демон cpulimit работает», если служба запущена, или «демон cpulimit не работает», если служба не запущена. Код:

sudo service cpulimit status

Запуск службы cpulimit Вы можете вручную запустить демон cpulimit, который начнет пропускать потребление ресурсов процессора. Код:

sudo service cpulimit start

Стоп cpulimit сервис Команда Stop останавливает демон cpulimit (таким образом, новый процесс не будет ограничен), а также устанавливает для всех существующих ограниченных процессов полный доступ к ЦП, как это было до запуска cpulimit. Код:

sudo service cpulimit stop

Перезапустите службу cpulimit.Если вы измените некоторые параметры переменных в /usr/bin/cpulimit_daemon.sh, например CPU_LIMIT, DAEMON_INTERVAL, BLACK_PROCESSES_LIST или WHITE_PROCESSES_LIST, то после изменения параметров вы должны перезапустить службу. Код:

sudo service cpulimit restart
  1. ПРОВЕРЬТЕ ПОТРЕБЛЕНИЕ ЦП С ИЛИ БЕЗ CPULIMIT DAEMON

без демона 1. остановите демон cpulimit (остановка службы sudo cpulimit) 2. выполнять ресурсоемкие задачи в фоновом режиме 3. выполнить команду: top и проверить столбец% CPU Результат% CPU, вероятно, составляет более 20% для каждого процесса.

с включенным демоном 1. запустить демон cpulimit (запуск службы sudo cpulimit) 2. выполнять те же задачи, интенсивно использующие процессор в фоновом режиме 3. выполнить команду: top и проверить столбец% CPU Результат% CPU должен составлять максимум 20% для каждого процесса. Примечание: не забывайте, что в начале% CPU может быть больше 20%, потому что демон должен отлавливать нарушающий процесс с интервалом в 3 секунды (установлен в скрипте по умолчанию)

  1. ЕСЛИ ИСПОЛЬЗУЕТ КОМПЬЮТЕР SMP

Я тестировал этот код на компьютере с двухъядерным процессором Intel, который ведет себя как компьютер SMP. Не забывайте, что команда top, а также cpulimit по умолчанию работают в режиме Irix, где 20% означает 20% одного процессора. Если имеется два ЦП (или двухъядерный), то общий% ЦП может составить 200%. В верхней команде режим Irix можно отключить командой I (нажатие + i при запуске верхней команды) и включить режим Solaris, где общее количество ЦП делится на количество ЦП, поэтому% ЦП может быть не более 100 % на любом количестве процессорного компьютера. Пожалуйста, прочитайте больше информации о верхней команде на главной странице руководства (поиск для команды I). Пожалуйста, прочитайте больше о том, как cpulimit работает на компьютере SMP, на официальной странице cpulimit.

Но как демон cpulimit работает на компьютере SMP? Всегда в режиме Irix. Поэтому, если вы хотите потратить 20% мощности ЦП на двухпроцессорном компьютере, 40% следует использовать для переменной CPU_LIMIT в сценарии демона cpulimit.

  1. УДАЛЕНИЕ ПРОГРАММЫ CPULIMIT DAEMON И CPULIMIT

Если вы хотите избавиться от демона cpulimit, вы можете очистить свою систему, удалив демон cpulimit и удалив программу cpulimit.

  1. Стоп демон cpulimit Код:

    служба sudo cpulimit stop # Остановить демон cpulimit и все процессы cpulimit

  2. Удаление демона из процедуры загрузки Код:

    sudo update-rc.d -f cpulimit remove # Удалить символические ссылки

  3. Удалить процедуру загрузки Код:

    sudo rm /etc/init.d/cpulimit # Удалить сценарий загрузки cpulimit

  4. Удалить демон cpulimit Код:

    sudo rm /usr/bin/cpulimit_daemon.sh # Удалить скрипт демона cpulimit

  5. Удалить программу cpulimit Код:

    sudo apt-get удалить cpulimit

  6. Удалить программу gawk Если вам не нужна эта программа для любого другого скрипта, вы можете удалить ее. Код:

    sudo apt-get remove gawk

  7. ПРИМЕЧАНИЕ ОБ АВТОРАХ

Я только что написал демон для cpulimit (скрипты bash выше). Я не автор проекта cpulimit. Если вам нужна дополнительная информация о программе cpulimit, пожалуйста, прочитайте официальную веб-страницу cpulimit: http://cpulimit.sourceforge.net/.

С уважением, Abcuser

6 голосов
/ 22 декабря 2008

Зачем ограничивать процент загрузки процессора, если вы можете просто настроить приоритет процесса, используя renice? Использование renice и установка низкого приоритета позволяет процессу по-прежнему использовать 100% процессора, если он доступен, но любой другой процесс с более высоким приоритетом получит процесс, когда он ему понадобится, практически без заметной задержки.

4 голосов
/ 19 сентября 2010

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

Я только что установил апплет аппаратных датчиков для gnome, настроил сигналы тревоги для высоких и низких температур на CPU, а затем настроил следующие команды для каждого сигнала тревоги:

низкий:

mv /tmp/hogs.txt /tmp/hogs.txt.$$ && cat /tmp/hogs.txt.$$ | xargs -n1 kill -CONT

высокая:

touch /tmp/hogs.txt && ps -eo pcpu,pid | sort -n -r | head -1 | gawk '{ print $2 }' >> /tmp/hogs.txt && xargs -n1 kill -STOP < /tmp/hogs.txt

Хорошая новость заключается в том, что мой компьютер больше не перегревается и не падает. Недостатком является то, что процессы терминала отсоединяются от терминала, когда они останавливаются, и не воссоединяются, когда они получают сигнал CONT. Другое дело, что если это была интерактивная программа, которая вызывала перегрев (например, определенный плагин для веб-браузера!), То она зависла бы в середине того, что я делаю, в то время как она ждала, пока процессор остынет. Было бы лучше, если бы масштабирование ЦП позаботилось об этом на глобальном уровне, но проблема в том, что у меня есть только две выбираемые настройки на моем ЦП, а медленная настройка недостаточно медленная, чтобы предотвратить перегрев.

Просто повторяем здесь, это не имеет ничего общего с приоритетом процесса, повторной фиксацией и, очевидно, не имеет ничего общего с остановкой заданий, которые выполняются в течение длительного времени. Это связано с тем, что загрузка ЦП не может оставаться на уровне 100% слишком долго, поскольку аппаратное обеспечение не может достаточно быстро отводить тепло при работе на полную мощность (неактивный ЦП генерирует меньше тепла, чем полностью загруженный ЦП).

Некоторые другие очевидные возможности, которые могут помочь:

Понизьте общую скорость процессора в BIOS

Замените радиатор или повторно нанесите термальный гель, чтобы посмотреть, поможет ли это

Очистить теплоотвод сжатым воздухом

Заменить вентилятор процессора

[править] Примечание: больше не перегревается при 100% CPU, когда я отключаю переменную скорость вентилятора в BIOS (asus p5q pro turbo). Когда процессор полностью загружен, каждое ядро ​​достигает максимума 49 градусов Цельсия.

2 голосов
/ 10 апреля 2015

Использование cgroups ' cpu.shares ничего не делает, чего бы не стоило значение nice . Звучит так, будто вы действительно хотите задушить процессы, что определенно можно сделать.

Вам потребуется использовать один или два сценария и / или отредактировать / etc / cgconfig.conf , чтобы определить нужные параметры.

В частности, вы хотите отредактировать значения cpu.cfs_period_us и cpu.cfs_quota_us . Затем процессу будет разрешено работать в течение cpu.cfs_quota_us микросекунд в cpu.cfs_period_us микросекунд.

Например:

Если cpu.cfs_period_us = 50000 и cpu.cfs_quota_us = 10000 , тогда процесс получит 20% от максимального времени ЦП, независимо от того, что еще происходит.

На этом скриншоте я дал процессу 2% процессорного времени:

2% CPU time

Что касается процесса, то он работает на 100%.

Настройки cpu.shares , с другой стороны, могут и будут использовать 100% времени простоя ЦП.

В этом похожем примере я привел процесс cpu.shares = 100 (из 1024):

cpu.shares

Как вы можете видеть, процесс все еще занимает все время простоя ЦП.

Ссылки:

http://manpages.ubuntu.com/manpages/precise/man5/cgconfig.conf.5.html http://kennystechtalk.blogspot.co.uk/2015/04/throttling-cpu-usage-with-linux-cgroups.html

2 голосов
/ 25 апреля 2014

У меня также была необходимость ограничивать процессорное время для определенных процессов. Cpulimit - хороший инструмент, но мне всегда приходилось вручную определять PID и вручную запускать cpulimit, поэтому я хотел что-то более удобное.

Я придумал этот скрипт bash:

#!/bin/bash

function lp
{

ps aux | grep $1 | termsql "select COL1 from tbl" > /tmp/tmpfile

while read line
do
    TEST=`ps aux | grep "cpulimit -p $line" | wc -l`
    [[ $TEST -eq "2" ]] && continue #cpulimit is already running on this process
    cpulimit -p $line -l $2
done < /tmp/tmpfile

}

while true
do
    lp gnome-terminal 5
    lp system-journal 5
    sleep 10
done

В этом примере время процессора каждого экземпляра gnome-терминала ограничивается 5%, а время процессора каждого экземпляра системного журнала - до 5%.

В этом примере я использовал другой сценарий, который я назвал под названием termql, чтобы извлечь PID. Вы можете получить его здесь: https://gitorious.org/termsql/termsql/source/master:

1 голос
/ 26 сентября 2013

Вы можете ограничить количество процессорного времени с помощью cgroups. ОС будет обрабатывать управление ресурсами так же, как вы задаете вопрос.

Вот вики с примерами: https://wiki.archlinux.org/index.php/Cgroups

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

1 голос
/ 22 декабря 2008

PS + GREP + NICE

1 голос
/ 22 декабря 2008

вижу как минимум два варианта:

  • Используйте "ulimit -t" в оболочке, которая создает ваш процесс
  • Использовать "nice" при создании процесса или "renice" во время выполнения
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...