Ограничение потребления ресурсов процессов в Unix

Материал из support.qbpro.ru

1. Обзор Запуск нескольких процессов в наших системах Linux требует от них совместного использования ресурсов, таких как центральный процессор, оперативная память и дисковое пространство. Чтобы избежать зависания ресурсоемких процессов, приводящих к зависанию системы, мы можем пожелать ограничить ресурсы, потребляемые другими процессами. В этом руководстве мы узнаем, как добавить ограничения в отношении процессора, оперативной памяти и дискового пространства. Мы будем использовать такие команды, как ulimit, cgroups, systemd-run, ionice, и nice. В некоторых случаях для выполнения этих команд потребуются разрешения суперпользователя.

2. Использование systemd-run systemd-run - это системный менеджер и менеджер служб, доступный напрямую в большинстве дистрибутивов Linux. Он занимается запуском процессов, служб и демонов. Этот инструмент позволяет нам добавлять ограничения непосредственно к конкретному процессу, который мы хотим запустить.

  • Например, мы можем запустить процесс с ограничением в 1 ГБ оперативной памяти:
$ systemd-run --scope -p MemoryLimit=1000M ./myProcess.sh

Здесь, myProcess.sh был запущен с помощью systemd-run и может обращаться только к указанной оперативной памяти.

  • Мы также можем использовать это, чтобы заставить процесс использовать только максимальный процент процессора:
$ systemd-run --scope -p CPUQuota=10% ./myProcess.sh
  • systemd-run позволяет нам сочетать ограничение как процессора, так и памяти:
$ systemd-run --scope -p MemoryLimit=1000M -p CPUQuota=10% ./myProcess.sh

3. Использование ulimit ulimit позволяет нам перезаписывать или создавать ограничения на оперативную память и дисковое пространство. Это встроенная функция оболочки bash.

3.1 Жесткие и мягкие ограничения Для всех пользователей в системе существует жесткое ограничение, устанавливаемое администратором. Затем существует мягкое ограничение, которое каждый пользователь может установить самостоятельно. Эти ограничения остаются в силе до тех пор, пока их не изменят.

  • Давайте установим мягкое ограничение в 1ГБ оперативной памяти для нашего текущего пользователя:
$ ulimit -Sv 1000000

Теперь любой запущенный нами процесс сможет использовать только 1ГБ оперативной памяти. Это ограничение повлияет на все запускаемые нами процессы в будущем, но мы можем изменить его перед запуском следующего процесса, если пожелаем.

  • С помощью ulimit мы также можем добавить ограничения на максимальный размер файла, создаваемого процессом, тем самым ограничивая используемое дисковое пространство:
$ ulimit -Sf 2000

Теперь все процессы, запускаемые нашим пользователем, будут способны создавать или копировать файлы только с максимальным размером 2 МБ. Следует отметить, что это ограничение распространяется на каждый файл.

  • Мы также можем комбинировать ограничения:
$ ulimit -Sv 1000000 -Sf 2000 && ./myProcess.sh

Здесь мы установили мягкие ограничения на оперативную память и размер файла и сразу же запустили myProcess.sh.

3.2 Как отменить ограничения, установленные с помощью ulimit Любой пользователь может изменить свое мягкое ограничение. Однако общие жесткие ограничения по-прежнему имеют приоритет. Однако изменить жесткое ограничение может только администратор.
Обычно мы указываем ограничение для ulimit численно. Однако для сброса ограничений ulimit мы можем использовать ключевое слово unlimited .

  • Давайте представим, что мы установили некоторые ограничения:
$ ulimit -Sv 1000000 -Sf 2000
$ ulimit -a
...
file size               (blocks, -f) 2000
...
virtual memory          (kbytes, -v) 1000000
...
  • Чтобы устранить их, мы устанавливаем вместо них неограниченный лимит:
$ ulimit -Sv unlimited -Sf unlimited 
$ ulimit -a 
...
file size (blocks, -f) unlimited 
...
virtual memory (kbytes, -v) unlimited 
...

4. Использование cpulimit может ограничить использование ЦП новыми или существующими процессамиcpulimit. Этот инструмент обычно доступен в Ubuntu.

  • Если мы используем другой дистрибутив, нам может потребоваться получить его:
$ sudo apt-get install cpulimit

4.1. Как использовать это в новом процессе

  • Мы можем напрямую запускать новые процессы с примененным ограничением ЦП:
$ cpulimit -l 20 firefox
Process 5202 detected

Здесь мы запустили новый процесс – браузер Firefox - с ограничением процессора в 20%.

4.2. Как использовать это в существующем процессе

  • Чтобы ограничить процесс, который уже запущен, мы должны указать имя процесса, которое будет найдено cpulimit:
$ firefox &
$ cpulimit -e firefox -l 30
Process 2666 detected

Здесь, cpulimit обнаружил процесс firefox с PID 2666 и ограничил процент процессора до 30%.

5. Использование ionice ionice позволяет нам ограничить, когда программе разрешено использовать ввод-вывод с системного диска. В настоящее время существует только четыре типа или класса планирования для ionice: 0, 1, 2 и 3.

  • Для запуска процесса в режиме ожидания, что означает, что он не будет использовать дисковый ввод-вывод, пока не пройдет определенный льготный период с момента последнего запроса на дисковый ввод-вывод, мы используем класс 3:
$ ionice --class 3 ./myProcess.sh
  • С классом 1 мы можем установить для процесса наивысший приоритет при вводе данных с диска:
$ ionice --class 1 ./myProcess.sh

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

6. Использование контрольных групп Группы управления (также известные как контрольные группы) - это группы ограничений, которые мы можем использовать для применения к нашим процессам. Мы можем думать о них как о фильтрах ограничения ресурсов, через которые должны проходить наши процессы.

  • Когда мы запускаем процесс через cgroup, будут применены все ограничения этой группы.

6.1. Как мы это получаем?

  • Возможно, что некоторые из команд cgroups недоступны в нашем дистрибутиве, поэтому нам, возможно, сначала потребуется их
становить:
$ apt-get install cgroup-tools

6.2. Создание групп

  • Теперь мы воспользуемся командой cgcreate для создания двух контрольных групп, которые мы будем использовать для запуска некоторых процессов:
$ sudo cgcreate -t $USER:$USER -a $USER:$USER -g cpu:/cpunormalusage
$ sudo cgcreate -t $USER:$USER -a $USER:$USER -g cpu:/cpulowusage

Здесь мы создали две cgroup, назначенные нашему пользователю. Для простоты мы использовали $USER и как пользователя, и как группу, хотя второе вхождение можно заменить на group, если мы предпочитаем.

  • Теперь нам нужно добавить ограничения к нашим контрольным группам:
$ cgset -r cpu.shares=512 cpulowusage

Здесь мы устанавливаем количество общих ресурсов для группы cpulowusage равным 512 с помощью cgset. Когда мы создаем cgroup, по умолчанию у нее 1024 общих ресурса. Чем больше общих ресурсов у группы, тем больше ресурсов она может получать от центрального процессора.

6.3. Запуск процесса

  • Чтобы запустить процесс в cgroup, мы используем команду cgexec:
$ cgexec -g cpu:cpulowusage firefox &

Выполнение приведенной выше команды запустит firefox в группе управления в фоновом режиме. Поскольку у него нет другой cgroup, с которой можно было бы конкурировать, у него будет доступ ко всему центральному процессору. Если мы запустим другой процесс в контрольной группе, он будет конкурировать с ним по количеству общих ресурсов.

6.4. Ограничение оперативной памяти До сих пор мы использовали контрольные группы для ограничения процессора. Мы также можем ограничить использование оперативной памяти. Для этого мы создадим новую cgroup и переопределим свойство с именем memory.limit_in_bytes.

  • Затем мы будем использовать комбинацию echo и tee, чтобы записать значение, конкретно для этой группы, в свойство:
$ sudo cgcreate -g memory:/memoryLimitGroup
$ echo $((1000000000)) | sudo tee /sys/fs/cgroup/memory/memoryLimitGroup/memory.limit_in_bytes

В нашем случае мы установили ограничение в 1ГБ.

  • Если мы хотим также ограничить пространство подкачки, мы переопределяем свойство memory.memsw.limit_in_bytes:
$ echo $((1000000000)) | sudo tee /sys/fs/cgroup/memory/memoryLimitGroup/memory.memsw.limit_in_bytes

Это добавляет 1ГБ пространства подкачки к нашей группе ограничений.

  • Теперь мы можем просто запустить процесс в фоновом режиме в этой контрольной группе:
$ cgexec -g memory:memoryLimitGroup firefox &

7. Манипулирование расписанием процессов 7.1. Использование nice Значение приятности варьируется от -20 до 19 и показывает потенциал процесса, выбранного центральным процессором для запуска.

  • Мы можем установить это значение перед запуском процесса:
$ nice -n 19 ./myProcess.sh

Здесь мы установили для удобства значение 19 и запустили myProcess. Чем выше точность, тем меньше процесс требует от планировщика, поэтому этому процессу будет отведено меньше процессорного времени, когда для других процессов требуется центральный процессор.

7.2. Использование renice

  • Чтобы изменить значение удобства процесса во время его выполнения, мы используем инструмент под названием renice:
$ ./myProcess.sh && ps aux | grep -i 'myProcess'
baeldung-reader       20935  0.0  0.0   6376  2420 pts/0    S+   10:16   0:00 grep --color=auto -i myProcess
$ renice -n 19 20935

В приведенном выше примере мы запустили процесс под названием myProcess, получили его PID и изменили его значение niceness на 19.

8. Заключение В этой статье мы узнали, как работать с ограничениями на процессор, оперативную память, пространство подкачки и дисковый ввод-вывод с использованием systemd-run, cpulimit, ulimit, ionice и cgroups. Мы также узнали, где эти ограничения могут применяться к процессу, который мы запускаем, к тому, который уже запущен, или ко всей системе.
Мы также узнали, как косвенно ограничить потребление ресурсов процессом, изменив его свойство niceness.

ИСТОЧНИК: