Как установить ulimit из скрипта Perl, который применяется к его дочерним элементам? - PullRequest
7 голосов
/ 09 февраля 2010

У меня есть Perl-скрипт, который выполняет различные этапы установки, чтобы настроить блок разработки для нашей компании. Он запускает различные сценарии оболочки, некоторые из которых вылетают из-за меньшего, чем требуется ulimit с (в частности, размер стека -s в моем случае).

Поэтому я бы хотел установить ulimit, который будет применяться ко всем скриптам (children), запускаемым из моего основного Perl, но я не уверен, как этого добиться - любые попытки вызвать ulimit из в пределах скрипта установите его только для той конкретной дочерней оболочки, которая немедленно завершается.

Я знаю, что могу позвонить ulimit до того, как запустить скрипт Perl или использовать /etc/security/limits.conf, но я не хочу, чтобы пользователь знал что-либо из этого - он должен знать только, как запустить скрипт, что должно позаботься обо всем этом для них.

Я также могу запускать ulimit каждый раз, когда запускаю команду, например, ulimit -s BLA; ./cmd, но я не хочу дублировать это каждый раз, и я чувствую, что есть лучшее, более чистое решение.

Еще один сумасшедший «обходной путь» - создать скрипт-обертку с именем BLA.sh, который бы устанавливал ulimit и вызывал BLA.pl, но, опять же, это мой хак, и теперь у меня будет 2 скрипта (я мог даже BLA.pl вызывает себя с помощью "ulimit -s BLA; ./BLA.pl --foo" и действует по-разному в зависимости от того, видит он --foo или нет, но это даже более хакерно, чем раньше).

Наконец, очевидно, я мог бы установить BSD :: Resource, но я бы хотел избежать использования внешних зависимостей.

Так как же способ установить ulimit из скрипта Perl и применить его ко всем дочерним элементам?

Спасибо.

Ответы [ 4 ]

12 голосов
/ 09 февраля 2010

Вы уже ответили на свой вопрос: используйте BSD :: Resource .

В ядре Perl нет ничего, что могло бы взаимодействовать с setrlimit. Если вы не можете (или не хотите) использовать стандартный метод, тогда вы должны использовать хак. Любой из методов, которые вы уже описали, будет работать. (Обратите внимание, что вы можете создать подпрограмму для добавления ulimit -s BLA; к каждой команде и затем использовать эту подпрограмму вместо system.)

4 голосов
/ 25 ноября 2011

Вот пример того, как установить предел ЦП без использования BSD :: Resource (но при условии, что системные заголовки perl есть). Чтобы адаптироваться к другим ресурсам, внесите очевидные изменения.

require 'syscall.ph';
require 'sys/resource.ph';

# set the soft cpu limit to 1 (second), and the hard limit to 10.
$rstruct = pack "L!L!",1,10; # L! means native long unsigned int.
syscall(&SYS_setrlimit,&RLIMIT_CPU,$rstruct);

Предполагается, что rlim_t на самом деле является unsigned long; Я не знаю, есть ли способ извлечь эту информацию из заголовков Perl.

4 голосов
/ 30 марта 2010

Вы всегда можете обернуть свой Perl в небольшой скрипт:

#!/bin/sh -- # --*-Perl-*--
ulimit -n 2048
exec /usr/bin/perl -x -S $0 ${1+"$@"}
#!/usr/bin/perl
#line 6

use strict;

# etc, etc....

Это ужасно, и, очевидно, время запуска скрипта будет немного больше.

1 голос
/ 10 февраля 2010

Я закончил тем, что добавил ulimit -s BLA к командам, которые нуждались в этом. Я специально не хотел использовать BSD :: Resource, потому что это не пакет Perl по умолчанию, и он отсутствовал примерно на половине существующих машин разработки. Взаимодействие с пользователем не было особым требованием.

...