If you have a process that need to run in the background, creating a daemon is the key. Some examples of what your can do:
- Wait for video files to be dropped via FTP and then process them
- Check for a recurring problem and report it to admin
- Monitor system load and report to the admin at a certain threshold
In this post we’ll take a look at how to create a Perl daemon script and how to get it to run as a daemon whenever the system is started. For the Perl script, a template will be created and for control of the daemon process, standard Debian facilities will be used.
What will be covered:
- Create the start/stop script in /etc/init.d
- Create the Perl daemon script in /usr/bin/
- Create the log file in /var/log/
- Get the daemon to start automatically when the system boots
- How to manage your daemon
The start/stop script starts and stops the daemon. It is also used by the system to start your daemon when the system starts.
The Perl daemon script contains your custom Perl code to run in the background. It executes your code every x number of seconds.
Create the Start/stop Script
Happily, Debian and therefore Ubuntu, supplies a template that uses the Debian start-stop-daemon command to start and stop daemons. It is only necessary to copy this template to a new file of the correct name and modify it for the purpose.
These scripts reside in the /etc/init.d/ directory. The script you create will have the exact same filename as the Perl daemon script you will create and the name cannot have a file extension – just the bare name.
Substitute your daemon’s name for “mydaemon” in the examples.
sudo cp /etc/init.d/skeleton /etc/init.d/mydaemon sudo chmod +x /etc/init.d/mydaemon
sudo vi /etc/init.d/mydaemon
Make changes to your start/stop script. Locate the header in the script:
PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="Description of the service" NAME=daemonexecutablename DAEMON=/usr/bin/$NAME DAEMON_ARGS="--options args" PIDFILE=/var/run/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME
Create the Perl Daemon Script
Use the Perl Daemon Script Template located at the end of this post. In the following, the script template is copied to /usr/bin/where executables specific to this system are located. Actually, you would copy the template to your home directory, make the changes and then copy the daemon script to /usr/bin/.
sudo cp daemon_template.pl /usr/bin/mydaemon sudo vi /usr/bin/mydaemon sudo chmod +x /usr/bin/mydaemon
The script template is commented with the changes that are needed. In particular, change the value of $daemonName to the exact name of your new daemon. Ten, add your custom code where # do something appears.
Prerequisites
The script uses File::Pid and POSIX from CPAN, so you’ll need to install that module:
sudo aptitude install cpan sudo cpan POSIX sudo cpan File::Pid
Create the Log File
We’ll create the log file so it has the correct ownership and permissions. The log fie has the daemon name appended with “.log”. It is located in the /var/log/ directory.
sudo touch /var/log/mydaemon.log sudo chmod 640 /var/log/mydaemon.log sudo chown root:adm /var/log/mydaemon.log
The permissions and ownership change allow adm group members to read the log, per convention. Add yourself to adm group to view logs.
Run your Daemon
As you have created a standard start/stop script for your daemon, you can start it the standard way:
sudo /etc/init.d/mydaemon start
Stop your Daemon
Similarly, your daemon is easy to stop and restart:
sudo /etc/init.d/mydaemon stop
sudo /etc/init.d/mydaemon restart
Automatically Start your Daemon
This command tells your system to start your daemon automatically when the system starts:
update-rc.d mydaemon defaults 99
To keep your daemon from starting, if needed:
update-rc.d -f mydaemon remove
Managing Daemons
List running daemons
Well-behaved daemons generally create a PID file in /var/run/. List that directory and your have a fair list of running daemons.
sudo ls /var/run/
Get PID for a particular daemon
If you know the name of a daemon and want to see if it is running and get its PID, use pgrep.
pgrep mydaemon
Also useful is the ps command, which list processes.
ps aux
The aux switch limits output to processes not associated with a terminal.
Show programs running as daemons
This line attempts to show programs that are running as daemons.
which `ps aux | cut -c 66- | cut -d\ -f 1` | sort | uniq
The Perl Daemon Script Template
#!/usr/bin/perl -w
#
# mydaemon.pl by Andrew Ault, www.andrewault.net
#
# Free software. Use this as you wish.
#
# Throughout this template "mydaemon" is used where the name of your daemon should
# be, replace occurrences of "mydaemon" with the name of your daemon.
#
# This name will also be the exact name to give this file (WITHOUT a ".pl" extension).
#
# It is also the exact name to give the start-stop script that will go into the
# /etc/init.d/ directory.
#
# It is also the name of the log file in the /var/log/ directory WITH a ".log"
# file extension.
#
# Replace "# do something" with your super useful code.
#
# Use "# logEntry("log something");" to log whatever your need to see in the log.
#
use strict;
use warnings;
use POSIX;
use File::Pid;
# make "mydaemon.log" file in /var/log/ with "chown root:adm mydaemon"
# TODO: change "mydaemon" to the exact name of your daemon.
my $daemonName = "mydaemon";
#
my $dieNow = 0; # used for "infinte loop" construct - allows daemon mode to gracefully exit
my $sleepMainLoop = 120; # number of seconds to wait between "do something" execution after queue is clear
my $logging = 1; # 1= logging is on
my $logFilePath = "/var/log/"; # log file path
my $logFile = $logFilePath . $daemonName . ".log";
my $pidFilePath = "/var/run/"; # PID file path
my $pidFile = $pidFilePath . $daemonName . ".pid";
# daemonize
use POSIX qw(setsid);
chdir '/';
umask 0;
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!";
open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!";
defined( my $pid = fork ) or die "Can't fork: $!";
exit if $pid;
# dissociate this process from the controlling terminal that started it and stop being part
# of whatever process group this process was a part of.
POSIX::setsid() or die "Can't start a new session.";
# callback signal handler for signals.
$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signalHandler;
$SIG{PIPE} = 'ignore';
# create pid file in /var/run/
my $pidfile = File::Pid->new( { file => $pidFile, } );
$pidfile->write or die "Can't write PID file, /dev/null: $!";
# turn on logging
if ($logging) {
open LOG, ">>$logFile";
select((select(LOG), $|=1)[0]); # make the log file "hot" - turn off buffering
}
# "infinite" loop where some useful process happens
until ($dieNow) {
sleep($sleepMainLoop);
# TODO: put your custom code here!
# do something
# logEntry("log something"); # use this to log whatever you need to
}
# add a line to the log file
sub logEntry {
my ($logText) = @_;
my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime(time);
my $dateTime = sprintf "%4d-%02d-%02d %02d:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec;
if ($logging) {
print LOG "$dateTime $logText\n";
}
}
# catch signals and end the program if one is caught.
sub signalHandler {
$dieNow = 1; # this will cause the "infinite loop" to exit
}
# do this stuff when exit() is called.
END {
if ($logging) { close LOG }
$pidfile->remove if defined $pidfile;
}
UPDATE:
Looks like there’s a page in French about this post: http://www.duncane.net/2011/02/25/perl-daemon/. Merci Duncane!



Hi,
Nice Code.. Working too.. i found log entry.. using logEntry(“log something”); function in “TODO” area..
so i guess it work with my codes too..
Thanks
Good to hear, Dinesh!
my $pidFile = $pidFIlePath . $daemonNam my $pid;
hey man i am getting error here can u please check it….
please do it i need it very urgent …
Sorry Gauvav, my mistake! I updated the code.
-A
my $pidFile = $pidFIlePath . $daemonNam . “.pid”;
hello friend can you please check this code again and according to me it might be
my $pidFile = $pidFilePath . $daemonName . “.pid”;
please check the code again…. and check spelling of scalar variables.
Friends it is also required to install the CPAN and use POSIX; File::Pid; modules previously in Perl to run this module.
Cpan Install : sudo apt-get cpan
Modules : sudo cpan POSIX
sudo cpan File::Pid
Enjoy Coding..!!
@Gaurav: You are absolutely right – I made the change.
That is an excellent point. I’ll add a note in the post. -A
please correct me if im wrong, but…
if you call exit in the parent process(at line 48 “exit if $pid;”) before the $pidfile object has been created, the END{} block is called and tries to cleanup $pidfile before it has been created? thus throwing an error/warning?
@nick: You are right, I updated the code. -A
hi , thank you for the code , it looks working !
but , it seems that log file is filled only when i stop the daemon , not while it’s running
@oznero:
I modified the begin log file @ line 63 to make the log file “hot” (removed buffering) so it will write to the log as it runs.
-Andrew
where i doing wrong?
sudo aptitude install cpan
sudo cpan POSIX
sudo cpan File::Pid
i haveinstalled all of that with default walues except where it asks for location country i set to my country Croatia thats all.
1. sudo cp /etc/init.d/skeleton /etc/init.d/dder
2. sudo chmod +x /etc/init.d/dder
3. sudo vi /etc/init.d/dder
4.
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC=”dder Module”
NAME=dder
DAEMON=/usr/sbin/$NAME
DAEMON_ARGS=”–options args”
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
5. thescript.pl file i typed
http://pastesite.com/20114
6. sudo cp thescript.pl /usr/bin/dder
7. sudo vi /usr/bin/dder
8. sudo chmod +x /usr/bin/dder
9. sudo touch /var/log/dder.log
10. sudo chmod 640 /var/log/dder.log
11. sudo chown root:adm /var/log/dder.log
12. sudo /etc/init.d/dder start
and nothing hapens



ps aux -> not there
htop -> not there
sudo ls /var/run/ -> not there
pgrep dder -> not there
i have fallowing all steps 5 times and i cant get it work!
anyone can help?
ubuntu server 8 something 0.4 TNL TLS?
@doublezero,
Looks like your script is “/usr/bin/dder”, but you have “/usr/sbin/dder” in “/etc/init.d/dder”.
Also, on a less important note, you might use logEntry() @line 40 of your script instead of printing directly to the log.
Best regards,
Andrew
damnt!
thanks for quick response!
yes “/usr/sbin/dder” was the problem but i copied it from this site here…
I’ve corrected the post so the paths are the same. Well done, doubezero! -A
-A ??
btw. nice code… iwe done years back something similar but havent use linux for a while…
Glad that it was useful. Not fancy, just understandable. -Andrew
Added a link to Duncane’s post.
Thanks for adding the link
And thanks for your howto that helped me when i needed it
Regards,
Duncane
hi,
has served me.
Muchas gracias por el how to, tengo problemas al usar el cpan por los modulos posix y file.
no logro instalr
Script works, if run a second time it wont start up, but if it is run a third time a second instance of the script is in memory.
So if you run the script 4 times then 2 stances in memory and so on and so forth.
I cannot find the problem.
Please help
mydaemon isn’t working for me. The hardware is a MX945GSE (Intel Atom N270 processor) running Debian Squeeze kernel version 2.6.32-5-686.
$ ls -ls /etc/init.d/mydaemon
8 -rwxr-xr-x 1 root root 4287 Sep 22 06:19 /etc/init.d/mydaemon
$ ls -ls /usr/bin/mydaemon
4 -rwxr-xr-x 1 root root 3263 Sep 22 06:11 /usr/bin/mydaemon
$ perl -c /usr/bin/mydaemon
/usr/bin/mydaemon syntax OK
$ sudo /etc/init.d/mydaemon start
$
$ sudo ls /var/run | grep mydaemon
$
$ sudo more /var/log/mydaemon.log
$
I checked that the POSIX and File::Pid modules are installed, with cpan -a
I edited /etc/init.d/mydaemon as indicated above and set the permissions. When I try to start mydaemon, nothing happens … no mydaemon running, no logging.
I’d be grateful for suggestions about where to go from here. I’ve tried seeing how far the perl mydaemon gets in the debugger but things go sideways when I get to the fork so I can’t see past that. Code I put immediately after open LOG, “>>$logFile”; to write to the logFile, doesn’t get executed because nothing appears in the log.
I can’t see the pid file after I start the daemon. And there are no warnings or errors.
What did I miss?