我该如何在Perl脚本内设置一个适用于其子进程的ulimit限制?

9
我有一个Perl脚本,用于为我们公司设置开发环境的各种安装步骤。它运行各种shell脚本,其中一些由于较低的ulimit(特别是我的情况下的堆栈大小-s)而崩溃。
因此,我想设置一个ulimit,适用于从我的主Perl脚本启动的所有脚本(子进程),但我不确定如何实现这一点 - 尝试从脚本内部调用ulimit只会在该特定子shell上设置它,然后立即退出。
我知道可以在运行Perl脚本之前调用ulimit或使用/etc/security/limits.conf,但我不希望用户知道任何这些信息 - 他们应该只知道如何运行脚本,脚本应该为他们处理所有内容。
我也可以每次运行命令时运行ulimit,例如ulimit -s BLA; ./cmd,但我不想每次都重复这样做,感觉有更好、更清晰的解决方案。
另一个疯狂的“解决办法”是创建一个名为BLA.sh的包装器脚本,它将设置ulimit并调用BLA.pl,但这也是一个hack,现在我有两个脚本了(我甚至可以让BLA.pl使用“ulimit -s BLA; ./BLA.pl --foo”调用自身,并根据是否看到--foo而行事不同,但这比以前更hack)。
最后,显然我可以安装BSD::Resource,但我想避免使用外部依赖项。
那么,从Perl脚本内部设置ulimit并使其适用于所有子进程的方法是什么呢?
谢谢。

4
可以使用BSD :: Resource。或者,编译自己的XS模块以执行相同的操作。虽然不知道为什么要这样做。 - ysth
4个回答

13

你已经回答了自己的问题:使用BSD::Resource

在 Perl 核心代码中没有与setrlimit交互的任何内容。如果您不能或不想使用标准方法,则必须使用一种hack方法。您已经描述的任何方法都可以工作。(请注意,您可以创建一个子例程来将ulimit -s BLA;插入到每个命令前面,然后使用该子例程而不是system。)


1
我不想使用外部依赖,正如我所提到的。这个脚本本身是一个为全新机器安装程序。如果有一种方法可以不用任何模块来完成它,我更愿意采用那种方法。一定有更好的解决方案... - Artem Russakovskii
1
好的,你可以直接按照模块中的内容进行操作。并不是说你不能查看源代码。 - brian d foy
@brian d foy,该模块需要XS,因此自定义模块的安装工作量与CPAN版本相同。 - cjm
1
定制模块总是更费力。这就是其中的讽刺。模块只是文件中的代码,但不知怎么地,人们会认为他们不允许查看它们。 - brian d foy

5
这里有一个示例,展示了如何在不使用BSD::Resource的情况下设置CPU限制(但假设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 实际上是无符号长整型;我不知道是否有办法从 Perl 标头中提取这些信息。

Perl在5.14.2及之前的版本中提供了"sys/resource.ph",但在5.20.2及以后的版本中不再提供。 - Onlyjob

4

您可以在一个小的shell脚本中包装您的perl代码:

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

use strict;

# etc, etc....

这看起来不太美观,而且显然,脚本启动时间会稍微长一些。


请注意,在Ubuntu/debian上会出现错误:/bin/sh: 0: Illegal option --。请参阅man perlrun以获取正确的语法。特别是,perl开始注释行应该单独成行。 - arielf

2
我最终将 ulimit -s BLA 添加到需要使用它的命令前。我特意没有选择BSD::Resource,因为它不是默认的Perl包,并且在大约一半的现有开发机器上缺失。无需用户交互是一个具体的要求。

十二年后,我面临着同样的问题。是否有更好(更新)的解决方案? - mabalenk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接