tags:

views:

436

answers:

5

I want to run a Perl script with some while(1) loop in the background on a unix machine until I kill it.

This is a remote computer to which I don't have administrative permissions (so for some reason, I can't use Daemon::Generic::While1), I log to it through SSH, and I want it to continue to run after I log out.

One way I found out is write something like this to bash:

nohup ./my_script.pl &

Is there some other, more preferable way to do it?

Editing the crontab is forbidden on that computer (while running background and long-lasting processes isn't).

+1  A: 

I believe this should work from within your perl script.

$SIG{ HUP } = 'IGNORE';

Note the man page doc for nohup says:

To do this, nohup sets the SIGHUP signal(3) (``terminal line hangup'') to be ignored, then executes utility along with any arguments.

Taylor Leese
A: 

Running the job in the background from the shell is fine, depending on how much manual labor you wish to put into making sure it's running continuously.

I would use crontab's @reboot (and possibly a regular checkup as well). But then you need to take into consideration that the process might be started multiple times. Simplest way to handle that is having a lock-file. If the file is locked, exit, else continue to the task. Remember to use non-blocking checks, else you risk hogging unnecessary system resources with dead processes.

screen is also an option if it's available.

crontab + screen can be combined.

editing crontab is forbidden on that computer.
Karel Bílek
Then you can't make sure that the process runs continuously (i.e. after a reboot). screen and nohup/trapping the SIGHUP are still valid ways to go.
Word of advice, ask the admin before putting any background processes on that machine. If you're not allowed crontab, admin might not like you going around it. Perhaps you'll be allowed if you ask nicely :)
etlerant: I already did, of course, and it IS ok. :-)
Karel Bílek
+1  A: 

Snippet is in perldoc perlipc:

use POSIX 'setsid';

sub daemonize {
    chdir '/'               or die "Can't chdir to /: $!";
    open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
    open STDOUT, '>/dev/null'
                            or die "Can't write to /dev/null: $!";
    defined(my $pid = fork) or die "Can't fork: $!";
    exit if $pid;
    setsid                  or die "Can't start a new session: $!";
    open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
}

But I'm not sure whether setsid will work if you're not root. If not, try to double-fork after closing standard handles.

some links: howto, daemonize

Artur
+1  A: 
use Proc::Daemon;
Proc::Daemon::Init;

That's what I use for my Sendmail filter program and probably the easiest way to go. The module is available via CPAN.

John Cavan
If he can't use Daemon::Generic::While1 because he can't get it installed, why would Proc::Daemon work better? Is it in the Perl core module list - if not, it won't help much.
Jonathan Leffler
I can get it installed (I modified CPAN to work without root password), but it tells me something about ability to write into /var/run
Karel Bílek
Hmm... I looked at the source and the module, itself, is not attempting to write to /var/run (at least on the version I'm using). It's a pretty small module, so you may want to just have a look at it and make a more personal version with the minimum code you require.
John Cavan
Yep, the one I'm using isn't doing that. Are you using Daemon::Generic or something similar as well?
John Cavan
I was talking about Daemon::Generic with the /var/run, not Proc::Daemon. I haven't tried that one, yet.
Karel Bílek
Daemon::Generic will write a pid file, but you can configure where it writes it. http://www.cpan.org/modules/by-module/Daemon/Daemon-Generic-0.61.readme
John Cavan
John Cavan: Oh, I somehow missed that!
Karel Bílek
That happens. :)
John Cavan
+1  A: 

You need to close stdout, stderr, stdin, otherwise you are still bound to that specific TTY

./my_script.pl >/dev/null 2>&1 </dev/null &

This should do the trick.

Hayato