Re: daemon with Perl on Linux
by Joost (Canon) on Nov 28, 2007 at 21:16 UTC
|
Looking at the source of Proc::Deamon, it actually binds STDIN STDOUT and STDERR to /dev/null, so none of them will be bound to your terminal. It also uses fork() and POSIX::setsid() which should ensure that the process is completely disconnected from the terminal in all other ways. (update: note that this is more or less exactly what a daemon IS. if you don't want this behaviour, you probably don't want to run your code as a daemon at all)
Daemons usually don't read anything from STDIN anyway (since they're supposed to be run completely in the background). Is there a reason you want to use STDIN to read from a socket instead of opening the socket in the daemon process?
It may make sense to put the "main code" in a separate module (see perlmod) for two reasons: one, so you can logically separate the daemon setup code from the processing code (i.e. just to make it easy to find the code you want and ignore the code you're not currently interested in); and two, if you put the processing code in a module you can use that same processing code in a program that doesn't act as a daemon (for instance, when testing the processing code, you can call it from a simple test script that gives output to STDOUT).
| [reply] |
|
|
OK, now I am confused. When script is listening for the data on the socket, isn't STDIN whatever script receives from that socket? If so, then whenever I make the script to run as a daemon, I won't be able to receive anything on the socket since STDIN will be detached. Am I right? What I have is a script listening for the data on the socket, and I want that script to run in the background all the time and process whatever I get from that socket. By the way, how should I enable this daemon to run at startup? Is it enough just to add it to one of startup files, or should I use runlevel folders?... Thanks for the help.
| [reply] |
|
|
$ my-program < a-file
# or
$ some-program | some-other-program
etc.
In general when you open a socket you get/use a new filehandle especially for that socket, since even though it's possible to re-open STDIN in some other way later (through a socket or file or whatever) that would IMO just be confusing.
Though most unix systems have a fairly similar ways to deal with startup/shutdown scripts through various runlevel files etc, the differences in how to administrate those files easily are different enough that you should probably just look up your system's documentation.
If you want to become better informed about all these issues, I recommend Advanced Programming in the UNIX Environment (2nd edition).
| [reply] [d/l] |
Re: daemon with Perl on Linux
by Akoya (Scribe) on Nov 28, 2007 at 20:45 UTC
|
I recently had to write a daemon. Due to corporate policies, I was unable to use non-core modules. The shell of the daemon is actually not very complex though...
use POSIX qw{ setsid getcwd close sysconf _SC_OPEN_MAX };
...
foreach my $i (0 .. openmax()) {
POSIX::close($i);
}
open(STDIN, "+>/dev/null");
open(STDOUT, "+>&STDIN");
open(STDERR, "+>&STDIN");
# ignore these signals
for (qw(TSTP TTIN TTOU PIPE POLL STOP CONT CHLD)) {
$SIG{$_} = 'IGNORE' if (exists $SIG{$_});
}
# handle these signals
for (qw(INT HUP ABRT QUIT TRAP TERM)) {
$SIG{$_} = 'interrupt' if (exists $SIG{$_});
}
unless (my $pid = fork()) {
exit if $pid;
POSIX::setsid; # set session id
chdir '/'; # change to root directory
umask 0; # clear the file creation mask
while(1) {
# do whatever your daemon needs to do ...
}
}
sub interrupt {
# do whatever to gracefully shutdown
...
die "$0 terminated successfully.\n";
}
Hope this is useful to you. As always, any suggestions are welcome. --Akoya
| [reply] [d/l] |
|
|
I found a couple of scripts similar to this one. As far as I understand, this script will do check ups on "whatever daemon needs to" check on. But what if my daemon needs to listen to the socket, but not to do any kind of check ups? Can I somehow to implement that? It might sound dumb to you, but I am newbie... :]
| [reply] |
Re: daemon with Perl on Linux
by jettero (Monsignor) on Nov 28, 2007 at 19:48 UTC
|
I'm not familiar with that particular module. If you want to get a really simple service up quickly, I'd look at Net::Daemon. If you scroll down to the example, you can just cut and paste that and edit to suit your needs.
| [reply] |
Re: daemon with Perl on Linux
by tuxz0r (Pilgrim) on Nov 28, 2007 at 20:59 UTC
|
Something else to look at might be POE, which makes it really easy to write daemon processes, servers and more under an event driven style of coding. We've been looking it over here at my work and it sure beats coding up background servers by hand.
---
echo S 1 [ Y V U | perl -ane 'print reverse map { $_ = chr(ord($_)-1) } @F;'
Warning: Any code posted by tuxz0r is untested, unless otherwise stated, and is used at your own risk.
| [reply] |
Re: daemon with Perl on Linux
by rimvydazas (Novice) on Nov 30, 2007 at 20:01 UTC
|
Ok, I added the following subroutine to my main script. Maybe it sounds funny, but where exactly in the main script I should run this subroutine? My script starts with "use" thingies, then global variables, command arguments (%ARGV), and the rest subroutines and socket connections.
sub daemonize {
# Change current working directory to root
chdir("$logroot") or die "Cannot change to $logroot: $!";
# Set umask to 0
umask(0);
# Detach STD file handles from the terminal
open (STDIN,"/dev/null") or die "Cannot read to /dev/null:
+$!";
open (STDOUT,">>$stoutp") or die "Cannot write to $stoutp:
+$!";
open (STDERR,">>$sterr") or die "Cannot write to $sterr: $!
+";
# PID forking
defined(my $pid = fork) or die "Cannot fork: $!";
exit if $pid;
setsid or die "Cannot set session ID: $!";
}
By the way, is there any way to assign specific PID for the process? The thing is that I need to start three processes from the same script to listen on three different ports. I need to check if these processes are running using cron. | [reply] [d/l] |