How to run a Perl script as daemon in background?
Question
How to run a Perl script as daemon in background?
Running a Perl script as a daemon means detaching it from the terminal and letting it run silently in the background, independent of any user session. This is common in system administration when you want your Perl script to act like a service or background process.
In Perl, there is no built-in daemonize function, but you can implement the required steps manually or use core modules like POSIX. The typical steps to daemonize a process are:
- Fork and exit the parent to ensure the process runs in the background.
- Create a new session using
setsid()to detach from any controlling terminal. - Change the working directory to
/(optional but recommended). - Redirect standard input/output/error to
/dev/nullor a log file to avoid terminal I/O. - Handle signals properly (like
SIGPIPEorSIGHUP) if needed.
Why these steps?
The fork() ensures the daemon is not a process group leader; setsid() creates a new session and makes the daemon the leader, detaching from the terminal. Changing to root directory avoids holding directories in use. Redirecting stdio prevents accidental terminal output or input that can cause hangs.
Example Perl daemon code
The following example runs as a background daemon printing a heartbeat counter every 5 seconds to demonstrate it's alive. You can customize it to your workload. It prints to STDOUT, so in real usage you should redirect output to a log file.
use strict;
use warnings;
use POSIX qw(setsid);
# Daemonize the process
sub daemonize {
# Fork the parent process
my $pid = fork();
if (!defined $pid) {
die "Cannot fork: $!";
}
if ($pid) {
# Parent exits, child continues
exit 0;
}
# Become session leader
setsid() or die "Cannot start a new session: $!";
# Fork again to prevent reacquire terminal
$pid = fork();
if (!defined $pid) {
die "Cannot fork second time: $!";
}
if ($pid) {
exit 0;
}
# Change working directory to root
chdir '/' or die "Can't chdir to /: $!";
# Clear file creation mask
umask 0;
# Redirect STDIN, STDOUT, STDERR to /dev/null
open STDIN, '<', '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>', '/dev/null' or die "Can't write /dev/null: $!";
open STDERR, '>', '/dev/null' or die "Can't write /dev/null: $!";
}
# Daemonize the script
daemonize();
# Main daemon loop
my $count = 0;
while (1) {
$count++;
open my $log, '>>', '/tmp/perl_daemon.log' or die "Cannot open log file: $!";
print $log scalar(localtime), " Daemon heartbeat #$count\n";
close $log;
sleep 5;
}
Explanation
fork(): The first fork and parent exit lets the shell prompt return and ensures we run in the background.setsid(): Starts a new session and detaches from any tty.- A second
fork(): This prevents the process from acquiring a controlling terminal again. chdir('/'): Avoids locking current directories.umask 0: Clears the creation mask for newly created files.- Redirects STDIN/STDOUT/STDERR to
/dev/null: A common daemon practice. - The daemon writes heartbeat messages to
/tmp/perl_daemon.lograther than STDOUT now that it's detached.
Common pitfalls
- Not double-forking will allow the daemon to potentially reacquire a controlling terminal.
- Neglecting to redirect standard handles can cause the daemon to hang if input/output blocks.
- Not changing directories can prevent unmounting of filesystems or cause other unexpected locks.
- Careful error handling is important for robust daemons.
- In real setups, consider signal handling to allow clean shutdown.
Additional notes
Some people prefer using core modules like Proc::Daemon from CPAN as it encapsulates these details, but for core-PERL-only and low-level control, this manual approach is reliable. The technique shown applies to Unix-like systems; Windows uses a different service and process model.
This approach has been standard since Perl 5 and POSIX availability. Ensure your system supports fork() and setsid() (most Unix/Linux do).
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 36ms
(empty)(empty)