zaLinux.ru

Как ограничить использование центрального процессора и памяти в Linux


Контроль использования центрального процессора и памяти в Linux

Скрипт timeout — это полезная программа мониторинга использования ресурсов. Она ограничивает потребление времени и памяти процессом Linux. Это позволяет вам запускать программу под контролем, указав ограничения по времени и памяти, если программа нарушит эти пределы, то она будет остановлена.

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

Программа не требует установки и у неё практически нет зависимостей (только Perl 5), она запускает программу вместе с её аргументами и контролирует её потребление ресурсов, если программа выходит за пределы, то она завершается, а пользователь уведомляется сообщением.

Программа timeout работает по принципу «чёрного ящика», то есть не требует какой-либо настройки самих процессов.

Обратите внимание, что данный скрипт не является одноимённой программой timeout из coreutils — это две разные программы.

Ещё нужно обязательно упомянуть Cgroups (Control Groups), которая контролирует потребление ресурсов системы на уровне ядра. По сравнению с рассматриваемым скриптом timeout, Cgroups сложнее в использовании, но и возможностей там больше.

Как установить timeout

Для работы скрипта на вашей системе Linux нужен установленный Perl 5 и смонтированная файловая система /proc.

Для проверки версии Perl на вашей системе Linux запустите следующую команду:

perl -v

Теперь нужно скачать сам скрипт — можно клонировать весь репозиторий https://github.com/pshved/timeout или скачать всего один файл:

wget https://raw.githubusercontent.com/pshved/timeout/master/timeout && sudo chmod 755 timeout

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

./timeout

Также программу можно вызывать по абсолютному пути (независимо от вашей текущей рабочей папки) — но у вас путь до файла будет другим:

/home/mial/bin/timeout

Опции timeout:

./timeout [опции] команда [аргументы команды]

Базовыми опциями являются:

  • -t T — устанавливает лимит времени CPU+SYS на T секунд
  • -m M — устанавливает лимит времени виртуальной памяти на M килобайт
  • TIMEOUT_IDSTR переменная_окружения — строка добавляемая к сообщению о нарушении лимитов использования ресурсов (для разграничения от строк, печатаемых самой командой). Само сообщение может быть:
  • TIMEOUT — лимит времени закончился
  • MEM — лимит памяти израсходован
  • HANGUP — обнаружено зависание (смотрите ниже)
  • SIGNAL - процесс timeout был убит сигналом

После этого сообщения печатается количество секунд, которое проработал процесс.

Как ограничить время выполнения программы (нагрузку на процессор)

Для ограничения времени выполнения используется опция -t после которой указывается количество секунд, которое должен проработать скрипт. Пример ограничения работы четыремя секундами:

./timeout -t 4 perl -e 'while ($i<10000000000) {$i++;}'

Вывод:

TIMEOUT CPU 4.10 MEM 10532 MAXMEM 10532 STALE 0 MAXMEM_RSS 3604
<time name="ALL">4120</time>

В выводе показана статистика использования процессора и памяти. Обратите внимание, что имеется ввиду процессорное время, то есть нагрузка на ЦПУ. Чтобы разница была более понятной, посмотрите на следующий пример:

./timeout -t 4 sleep 20

Он проработает не 4 секунды, а 20 секунд, поскольку нагрузка на процессор отсутствует. В выводе будет показано:

FINISHED CPU 0.00 MEM 5276 MAXMEM 5276 STALE 12 MAXMEM_RSS 824

Как ограничить потребление памяти

В следующем примере программа будет работать любое количество времени, но если она её потребление ресурсов превысит 10 гигабайт памяти, то она будет остановлена:

./timeout -m 10000000 perl -e 'while ($i<1000000000) {$a->{$i} = $i++;}'

Вывод:


MEM CPU 37.09 MEM 10055984 MAXMEM 10055984 STALE 0 MAXMEM_RSS 10053244
<time name="ALL">37110</time>

Посмотрите на скриншот, на нём видно, как программа постепенно увеличивала количество занятой памяти, а потом была завершена из-за превышения лимита:


Как ограничить использование процессорного времени и памяти

В следующем примере количество используемой памяти ограничено 1 гигабайтом и процессорное время ограничено 9 секундами:

./timeout -m 1000000 -t 9 perl -e 'while ($i<10000000000) {$x->{$i} = $i++;}'

Вывод:

MEM CPU 2.69 MEM 1031600 MAXMEM 1031600 STALE 0 MAXMEM_RSS 1029156
<time name="ALL">2720</time>

Как можно увидеть, было потреблено менее трёх секунд процессорного времени, а программа была завершена из-за превышения лимита памяти.

Ограничение нагрузки на процессор с множеством коротких дочерних процессов

./timeout -t 20 perl -e 'while(1){ system qw(perl -e while($i<5000000){$i++;}); }'

Вывод:

TIMEOUT CPU 20.09 MEM 21064 MAXMEM 21064 STALE 0 MAXMEM_RSS 8708
<time name="ALL">7400</time>

То есть программа timeout успешно подсчитывает не только ресурсы основного процесса, но и дочерних процессов.

Продвинутые опции

  • -p .*regexp1.*,ИМЯ1;.*regexp2.*,ИМЯ2 — собирает статистику для дочерних процессов с указанными командами. ИМЕНА определяют сегменты, а regexps (регулярные выражения в формате Perl) определяют совпадение дочерних процессов, которые попадают в эти сегменты.
    Если шаблон начинается с CHILD:, тогда в эту категорию собирается информация о работе дочерних совпадающих процессах (поиск совпадений выполняется по остальному шаблону). Обратите внимание, что это единственный способ собрать статистику потреблённого времени дочерними процессами, которые длятся только доли секунды.
  • -o файл_вывода — файл для сброса статистики сегментов, собранной опцией -p
  • --detect-hangups — выключить выявление зависаний. Если вы указали фрагмент опцией -p, тогда если CPU время в любом из фрагментов не увеличивается во время некоторого времени, то скрипт timeout приходит к выводу, что контролируемый процесс завис и выключает его.
  • --no-info-on-success — отключает вывод статистики использования если контролируемый процесс успешно завершил работу.
  • --confess, -c — при выключении контролируемого процесс возвращает его код выхода или сигнал+128. Это также приводит к тому, что timeout ожидает пока контролируемый процесс не завершиться. Без этой опции скрипт возвращает толь.
  • --memlimit-rss, -s — монитор лимита памяти RSS (resident set size)

Сбор информации о «тяжёлых» процессах:

./timeout -p '.*perl.*,PERL' perl -e 'for (1..20_000_000) {$i++;}'

Вывод:

FINISHED CPU 0.24 MEM 10532 MAXMEM 10532 STALE 0 MAXMEM_RSS 3552
<time name="PERL">260</time>

Сбор статистики о «лёгких» дочерних процессах

./timeout -t 10 -p '.*perl.*,PERL;CHILD:.*perl.*,KIDS' perl -e 'for (1..2_000) {system qw(perl -e while($i<500000){$i++;}); $i++;}'

Вывод:

TIMEOUT CPU 10.04 MEM 10532 MAXMEM 21064 STALE 0 MAXMEM_RSS 8700
<time name="PERL">70</time>
<time name="KIDS">10000</time>

В этом шаблоне легковесные дочерние процессы должны отслеживаться с помощью специального префикса CHILD:, сравните предыдущую команду и эту:

./timeout -t 10 -p '.*perl.*,PERL' perl -e 'for (1..2_000) {system qw(perl -e while($i<500000){$i++;}); $i++;}'

Вывод:


TIMEOUT CPU 10.03 MEM 21064 MAXMEM 21064 STALE 0 MAXMEM_RSS 8784
<time name="PERL">60</time>

Почему остальные не показаны в статистике? Все процессы запускаются из Perl, но короткоживущие не отслеживаются в полной мере, поскольку timeout не просыпается достаточно часто.

Выявление зависаний в программе:

./timeout --detect-hangups -p '.*sleep.*,SLEEP' -t 5 sleep 10000

Вывод:

HANGUP CPU 0.00 MEM 5276 MAXMEM 5276 STALE 6 MAXMEM_RSS 760

Более простой пример для остановки процесса, если он завис:

./timeout -t 4 --detect-hangups sleep 200

Вывод:

HANGUP CPU 0.00 MEM 5276 MAXMEM 5276 STALE 5 MAXMEM_RSS 764

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


Рекомендуемые статьи:

1 Комментарий

  1. Василий

    Благодарю за скрипт, поигрался с большим интересом. Оставлю в коллекции, может пригодится когда-нибудь =).

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *