How can I keep running a unix program in the background even if I log out?

Tag: unix Author: lym8118 Date: 2009-09-13

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).

Best Answer

My preferred method, and arguably the easiest, is using screen:

screen -d -m ./myProcess

comments:

Hah. I already forgot I ever asked this question. Screen is my tool of choice now, too :)

Other Answer1

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.

comments:

perfect! exactly what you need when there is no screen

Other Answer2

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.

Other Answer3

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

Other Answer4

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.

comments:

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.
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
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.
Yep, the one I'm using isn't doing that. Are you using Daemon::Generic or something similar as well?
Daemon::Generic will write a pid file, but you can configure where it writes it. cpan.org/modules/by-module/Daemon/Daemon-Generic-0.61.readme

Other Answer5

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.

comments:

editing crontab is forbidden on that computer.
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. :-)