Я бегу, pdftoppm
чтобы преобразовать предоставленный пользователем PDF в изображение с разрешением 300 точек на дюйм. Это прекрасно работает, за исключением случаев, когда пользователь предоставляет PDF с очень большим размером страницы. pdftoppm
выделит достаточно памяти для хранения изображения с разрешением 300 точек на дюйм такого размера, которое для 100-дюймовой квадратной страницы составляет 100 * 300 * 100 * 300 * 4 байта на пиксель = 3,5 ГБ. Злонамеренный пользователь может просто дать мне большой глупый PDF и вызвать все виды проблем.
Поэтому я хотел бы установить какое-то жесткое ограничение на использование памяти для дочернего процесса, который я собираюсь запустить - просто заставьте процесс умереть, если он попытается выделить больше, скажем, 500 МБ памяти. Это возможно?
Я не думаю, что ulimit может быть использован для этого, но есть ли однопроцессный эквивалент?
docker
?Ответы:
Есть некоторые проблемы с ulimit. Вот полезное прочтение на тему: Ограничение времени и потребления памяти программой в Linux , что приводит к инструменту тайм-аута , который позволяет распределять процесс (и его вилки) по времени или потреблению памяти.
Средство ожидания требует Perl 5+ и
/proc
смонтированной файловой системы. После этого вы копируете инструмент, например,/usr/local/bin
так:После этого вы можете «затянуть» ваш процесс за счет потребления памяти, как в вашем вопросе, вот так:
В качестве альтернативы вы можете использовать
-t <seconds>
и-x <hertz>
соответственно ограничить процесс по времени или ограничениям процессора.Этот инструмент работает путем проверки нескольких раз в секунду, если порожденный процесс не превысил свои установленные границы. Это означает, что на самом деле есть небольшое окно, в котором процесс потенциально может быть переподписан до того, как тайм-аут уведомит и убьет процесс.
Следовательно, более правильный подход, вероятно, будет включать cgroups, но это гораздо более сложная настройка, даже если вы используете Docker или runC, которые, среди прочего, предлагают более удобную для пользователя абстракцию вокруг cgroups.
источник
coreutils
утилите linux ! Таким образом, ответ потенциально опасен, если где-нибудь в вашей системе какой-то пакет содержит скрипт, ожидающий,timeout
что он станет стандартнымcoreutils
пакетом linux ! Я не знаю, упакован ли этот инструмент для таких дистрибутивов, как Debian.-t <seconds>
ограничение процесс через столько секунд?Другой способ ограничить это - использовать контрольные группы Linux. Это особенно полезно, если вы хотите ограничить выделение физической памятью процесса (или группы процессов) отдельно от виртуальной памяти. Например:
создаст группу управления с именем
myGroup
, ограничив набор процессов, выполняемых под myGroup, до 500 МБ физической памяти и до 5000 МБ подкачки. Чтобы запустить процесс в контрольной группе:Обратите внимание, что в современном дистрибутиве Ubuntu этот пример требует установки
cgroup-bin
пакета и редактирования/etc/default/grub
для измененияGRUB_CMDLINE_LINUX_DEFAULT
на:и затем запуск
sudo update-grub
и перезагрузка для загрузки с новыми параметрами загрузки ядра.источник
firejail
Программа также позволит вам начать процесс с ограничениями памяти ( с использованием контрольных групп и пространств имен , чтобы ограничить больше , чем просто память). В моих системах мне не нужно было менять командную строку ядра, чтобы это работало!GRUB_CMDLINE_LINUX_DEFAULT
модификация, чтобы сделать настройку постоянной? Я нашел другой способ сделать это постоянным здесь .swapaccount=1
в GRUB_CMDLINE_LINUX_DEFAULT?Если ваш процесс не порождает больше детей, которые занимают больше всего памяти, вы можете использовать
setrlimit
функцию. Более распространенный пользовательский интерфейс для этого используетulimit
команду оболочки:Это ограничит только «виртуальную» память вашего процесса, принимая во внимание - и ограничивая - память, которую вызываемый процесс делит с другими процессами, и память, отображаемая, но не зарезервированная (например, большая куча Java). Тем не менее, виртуальная память является наиболее близким приближением для процессов, которые становятся действительно большими, что делает указанные ошибки незначительными.
Если ваша программа порождает детей, и именно они распределяют память, она становится более сложной, и вы должны написать вспомогательные сценарии для запуска процессов под вашим контролем. Я написал в своем блоге, почему и как .
источник
setrlimit
сложнее для большего количества детей?man setrlimit
говорит мне, что «дочерний процесс, созданный с помощью fork (2), наследует ограничения своих родительских ресурсов. Ограничения ресурсов сохраняются в execve (2)»ulimit
подход помог мне сfirefox
«ы ошибкой 622816 - Загрузка большого изображения может„заморозить“браузер Firefox, или сбой системы ; который при загрузке с USB (из ОЗУ) имеет тенденцию к зависанию ОС, требуя жесткого перезапуска; теперь хотя быfirefox
вылетает сам, оставляя ОС в живых ... ура!Я использую приведенный ниже скрипт, который прекрасно работает.
Он использует cgroups черезОбновление: теперь он использует команды изcgmanager
.cgroup-tools
. Назовите этот скриптlimitmem
и поместите его в $ PATH, и вы можете использовать его какlimitmem 100M bash
. Это ограничит использование памяти и подкачки. Чтобы ограничить только память, удалите строку сmemory.memsw.limit_in_bytes
.edit: при установке Linux по умолчанию это ограничивает использование памяти, а не использование подкачки. Чтобы включить ограничение использования свопа, вам нужно включить учет свопа в вашей системе Linux. Сделайте это путем установки / добавления
swapaccount=1
в/etc/default/grub
так выглядит что - то вродеЗатем запустите
sudo update-grub
и перезагрузите компьютер.Отказ от ответственности: я не удивлюсь, если
cgroup-tools
также перерывы в будущем. Правильным решением было бы использовать API-интерфейсы systemd для управления cgroup, но для этой системы нет инструментов командной строки.источник
call to cgmanager_create_sync failed: invalid request
для каждого процесса, с которым я пытаюсь работатьlimitmem 100M processname
. Я на Xubuntu 16.04 LTS и этот пакет установлен.$ limitmem 400M rstudio limiting memory to 400M (cgroup limitmem_24575) for command rstudio Error org.freedesktop.DBus.Error.InvalidArgs: invalid request
есть идеи?percent
результатов приводит к нулю,expr
код состояния равен 1, и этот сценарий завершается преждевременно. рекомендуем изменить строку на:percent=$(( "$peak_mem" / $(( "$bytes_limit" / 100 )) ))
(ref: unix.stackexchange.com/questions/63166/… )В дополнение к инструментам
daemontools
, предложенным Марком Джонсоном, вы также можете рассмотреть,chpst
что находится вrunit
. В него входит сам Runitbusybox
, так что, возможно, он уже установлен.Страница man
chpst
показывает опцию:источник
Я использую Ubuntu 18.04.2 LTS, и скрипт JanKanis не работает для меня так, как он предлагает. Запуск
limitmem 100M script
ограничивает 100 МБ ОЗУ с неограниченным обменом.Запуск
limitmem 100M -s 100M script
завершается неудачно, так какcgget -g "memory:$cgname"
не имеет именованных параметровmemory.memsw.limit_in_bytes
.Поэтому я отключил своп:
источник
В любом системном дистрибутиве вы также можете использовать cgroups косвенно через systemd-run. Например, для вашего случая ограничения
pdftoppm
до 500M RAM, используйте:Примечание: это попросит вас ввести пароль, но приложение будет запущено как ваш пользователь. Не позволяйте этому вводить вас в заблуждение, заставляя вас думать, что команда нуждается в этом
sudo
, потому что это заставит команду работать от имени пользователя root, что вряд ли было вашим намерением.Если вы не хотите вводить пароль (в конце концов, как пользователь, которому вы владеете своей памятью, зачем вам нужен пароль для его ограничения) , вы можете использовать
--user
опцию, однако для этого вам понадобится включить поддержку cgroupsv2, что правильно теперь требует загрузки сsystemd.unified_cgroup_hierarchy
параметром ядра .источник