Here's some code to daemonize a program.
With the test daemon I've provided, it is easy to confirm
that the code runs even if you log off.
Here is the daemonizing code:
#!/usr/bin/perl -w
use strict;
use warnings;
use diagnostics;
use POSIX qw(setsid);
my $cmd = qq{./perl_delayer.pl};
fork_daemon($cmd);
exit 0;
#################################################
# Daemonize!
#################################################
sub fork_daemon
{
my ($cmd) = @_; # Pass a string or an array reference
my $pid_c = fork(); # Parent spawns Child
die "Cannot fork: $!" if !defined $pid_c;
if ($pid_c)
{
# ==== Parent ====
waitpid($pid_c, 0); # Zombies not allowed
return; # No attachment to grand-child
}
# ==== Child ====
my $pid_gc = fork(); # Child spawns Grand-Child
die "Cannot fork: $!" if !defined $pid_gc;
exit (0) if $pid_gc; # Child exits immediately
# ==== Grand-Child ====
# Grand-Child continues, now parented by init.
# Detach from controlling terminal and create new process group.
setsid() || die "Can't start a new session: $!";
# Close std* streams.
close STDIN;
close STDOUT;
close STDERR;
open STDIN , "< /dev/null";
open STDOUT, "> /dev/null"; # could use "> nohup.out"
open STDERR, "> /dev/null"; # could use ">> nohup.out"
# There is no reason to ignore SIGHUP.
# Since we've detached from the terminal, we won't
# be getting one when the user logs out.
# $SIG{HUP} = 'IGNORE';
exec(ref($cmd) eq "ARRAY" ? @$cmd : $cmd); # Run command
exit(0);
}
Here is the test daemon code, "perl_delayer.pl".
You will observe that the file created ("delayer.out")
gets the full countdown and is not affected by a logout.
#!/usr/bin/perl -w
use strict;
use warnings;
my $fname = "delayer.out";
open(OUT,">",$fname) || die("Cannot open $fname: $!");
select OUT; $| = 1; # make unbuffered
select STDOUT; $| = 1; # make unbuffered
my $count = 60;
while ($count--)
{
my $str = "$count: The time is now ".localtime()."\n";
print $str;
print OUT $str;
sleep 1;
}