tags:

views:

762

answers:

3

I have a Perl script that does various installation steps to set up a development box for our company. It runs various shell scripts, some of which crash due to lower than required ulimits (specifically, stack size -s in my case).

Therefore, I'd like to set a ulimit that would apply to all scripts (children) started from within my main Perl one, but I am not sure how to achieve that - any attempts at calling ulimit from within the script only set it on that specific child shell, which immediately exits.

I am aware that I can call ulimit before I run the Perl script or use /etc/security/limits.conf but I don't want the user to know any of this - they should only know how to run the script, which should take care of all of that for them.

I can also run ulimit every time I run a command, like this ulimit -s BLA; ./cmd but I don't want to duplicate this every time and I feel like there's a better, cleaner solution out there.

Another crazy "workaround" is to make a wrapper script called BLA.sh which would set ulimit and call BLA.pl, but again, it's a hack in my mind and now I'd have 2 scripts (I could even make BLA.pl call itself with "ulimit -s BLA; ./BLA.pl --foo" and act differently based on whether it sees --foo or not but that's even hackier than before).

Finally, apparently I could install BSD::Resource but I'd like to avoid using external dependencies.

So what is THE way to set the ulimit from within a Perl script and make it apply to all children?

Thank you.

+4  A: 

You've already answered your question: use BSD::Resource.

There isn't anything in the Perl core that interfaces with setrlimit. If you can't (or won't) use the standard method, then you have to use a hack. Any of the methods you've already described would work. (Note that you could create a subroutine to prepend ulimit -s BLA; to every command, and then use that sub instead of system.)

cjm
I don't want to use external deps, as I mentioned. The script itself is an installer for a potentially brand new machine. If there is a way to do it w/o any modules, I'd prefer to go for that approach. There has to be something better...
Artem Russakovskii
Well, you could just do what's in the module. It's not like you're forbidden from looking at the source.
brian d foy
@brian d foy, the module requires XS, so a custom module would be just as much work to install as the CPAN version.
cjm
A custom module is always more work. That's the irony of it. Modules are just code in files, but somehow people get the idea they aren't allowed to look at them.
brian d foy
A: 

I ended up prepending ulimit -s BLA to the commands that needed it. I specifically didn't want to go with BSD::Resource because it's not a default Perl package and was missing on about half of the existing dev machines. No user interaction was a specific requirement.

Artem Russakovskii
A: 

You can always wrap your perl in a little shell script:

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

use strict;

# etc, etc....

It's ugly, and obviously, script start up time will be slightly longer.

Gavin Brock