Perl detach process daemon

| 0 Comments | 0 TrackBacks

This is how a running process can detach itself from the shell and become a daemon. Not just from the shell but sometimes from another parent process such as an HTTP server. One characteristic of a daemon is that its parent process ID will be one, that of the init process. It would be a good thing to check that your PPID is not one before attempting to daemonize yourself.


#!/usr/bin/perl

use POSIX 'setsid';


defined (my $kid = fork) or die "Cannot fork: $!\n";

if ($kid) {

    # Parent runs this block

    exit(0);

} else {


    close STDIN;

    close STDOUT;

    close STDERR;

    setsid or die "Can't start a new session: $!";

    umask(0027); # create files with perms -rw-r----- 

    chdir '/' or die "Can't chdir to /: $!";


    open STDIN'<', '/dev/null' or die $!;

    open STDOUT, '>', '/dev/null' or die $!;

    open STDERR, '>>', '/tmp/mysql_install.log';


    defined (my $grandkid = fork) or die "Cannot fork: $!\n";

    if($grandkid){

        exit(0);

    }else{

         # my daemon is here.

        sleep(60);

        system("rpm -e --nodeps mysql-5.0.77-4.el5_4.1");

        system("yum install -y MySQL-client-5.5.22-1.linux2.6");

        system("yum install -y MySQL-devel-5.5.22-1.linux2.6");

        system("yum install -y MySQL-shared-compat-5.5.22-2.linux2.6");

    }

}



But in the above code, the parent is unaware of the detached process's ID. The parent of the daemon will be init and init will be responsible for cleaning after it. But if we want to still know what PID it is so that we can explicitly send a signal to it from the grandparent the detached grandchild will have somehow communicate his process ID back to the grandparent.


#!/usr/bin/perl

use POSIX 'setsid';


pipe(READER, WRITER) || die "pipe failed: $!\n";

defined (my $kid fork) or die "Cannot fork: $!\n";

if ($kid) {

    # Parent runs this block

   close(WRITER);

   my $line = <READER>;

   chomp $line;

   $daemon_pid = $line;

   close(READER) || warn "kid existed $?";

   waitpid($kid,0);

    exit(0);

else {

    close(READER);

    close STDIN;

    close STDOUT;

    close STDERR;

    setsid or die "Can't start a new session: $!";

    umask(0027); # create files with perms -rw-r----- 

    chdir '/' or die "Can't chdir to /: $!";


    open STDIN,  '<''/dev/null' or die $!;

    open STDOUT'>''/dev/null' or die $!;

    open STDERR'>>''/tmp/mysql_install.log';


    defined (my $grandkid fork) or die "Cannot fork: $!\n";

    if($grandkid){

        print WRITER "$grandkid\n";

        close(WRITER);

        exit(0);

    }else{

         # my daemon is here.

        sleep(60);

        system("rpm -e --nodeps mysql-5.0.77-4.el5_4.1");

        system("yum install -y MySQL-client-5.5.22-1.linux2.6");

        system("yum install -y MySQL-devel-5.5.22-1.linux2.6");

        system("yum install -y MySQL-shared-compat-5.5.22-2.linux2.6");

    }

}


We used pipes for this purpose. Notice that the grandchild ends it's PID with a newline when writing it to the grandparent. That's because the reader < and > will block until it reads a newline character.

No TrackBacks

TrackBack URL: http://www.farhadsaberi.com/cgi-bin/mt/mt-tb.cgi/22

Leave a comment

About this Entry

This page contains a single entry by Farhad Saberi published on February 4, 2013 10:31 PM.

Hierarchical data representation in SQL Netsted Sets was the previous entry in this blog.

How to swap two variables without using a temporary variable is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.