LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   How to efficiently daemonize a commando program in one line of Perl code. (https://www.linuxquestions.org/questions/linux-software-2/how-to-efficiently-daemonize-a-commando-program-in-one-line-of-perl-code-714948/)

brianpbarnes 03-27-2009 05:50 PM

How to efficiently daemonize a commando program in one line of Perl code.
 
Hi,
I have spawned child processes by using the posix library, forking a forking fork, checking the return values, closing all files, cding to /, looking at getppid(), setsid(), etc. This seems like a microsofteanishly overly complicated, fork bomb generating way to send a commando on a mission.

A generous genius Perl Monk who goes by NCW published a very slick, F=MA like Proc::Daemon module to do this in one line of code (Proc[colon colon]Daemon. Please ignore the weird icon).

From http://www.perlmonks.org/?node_id=31982 :
use Proc::Daemon;
Proc::Daemon::Init();

Here is a working demo program, bb.pl:
======================================================

#!/usr/local/bin/perl -w
use Time::HiRes qw( usleep gettimeofday tv_interval );
$stime = time;
&daemon();
printf("Elapsed time = %3.2f minutes.\n", (time - $stime) / 60);
exit;

sub daemon() {
%m2f = ("/media/20080331c" => "/home/brianp/20080331c.ls.txt",
"/media/20090116a" => "/home/brianp/20090116a.ls.txt",
"/media/20090127a" => "/home/brianp/20090127a.ls.txt");
foreach $mount (sort keys %m2f) {
$file = $m2f{$mount};
$cmd = "daemon.pl $mount $file";
printf("Cmd = \"$cmd\". %s.\n", scalar localtime);
system $cmd;
}
}

------------

Program daemon.pl:

#!/usr/local/bin/perl -w
use Proc::Daemon;

($mount, $outfile) = @ARGV;
open(OUT, ">$outfile") || die "Unable to >open $outfile. Bye!\n";
print(OUT "$0 $$ M=$mount, O=$outfile before daemon init...\n");
close OUT;
Proc::Daemon::Init();
open(OUT, ">>$outfile") || die "Unable to >>open $outfile. Bye!\n";
printf(OUT "$0 $$ %s.\n", scalar localtime);
$cmd = "ls -lR $mount";
print(OUT "Cmd = \"$cmd\".\n");
$rtn = `$cmd`;
print(OUT "Rtn = $rtn\n");
close OUT;
exit;

--------------
Main program STDOUT:
brianp@godzilla2:~/dvdread$ bb.pl
Cmd = "daemon.pl /media/20080331c /home/brianp/20080331c.ls.txt". Fri Mar 27 17:12:46 2009.
Cmd = "daemon.pl /media/20090116a /home/brianp/20090116a.ls.txt". Fri Mar 27 17:12:46 2009.
Cmd = "daemon.pl /media/20090127a /home/brianp/20090127a.ls.txt". Fri Mar 27 17:12:46 2009.
Elapsed time = 0.00 minutes.

--------------

Output example from 20090127a.ls.txt:
/home/brianp/bin/daemon.pl 23943 M=/media/20090127a, O=/home/brianp/20090127a.ls.txt before daemon init...
/home/brianp/bin/daemon.pl 23945 Fri Mar 27 17:12:46 2009.
Cmd = "ls -lR /media/20090127a".
Rtn = /media/20090127a:
total 3436980
-r--r--r-- 1 brianp root 129073 2009-01-27 13:24 bb.pl
<snip>

Notice the immediate execution at 17:12:46 suggesting that the child process took no time flat to return. And, notice the PIDs, 23943 vs 23945 confirming that the worker process is indeed a grandchild of the main process.

This is the slickest, simplest and most efficient worker process daemonization scheme I can imagine, one line of code and one use module.

I am going to use this scheme to have 4, simultaneous DVD reader/digester programs running to transfer all of the data on 1000+ DVDs to a database. My involvement will be nothing more than stuffing 4 dvd readers with random DVDs, kicking off the program, replacing the digested DVDs when the tray opens and sorting the read DVDs by date code. I could train a monkey to do this. Wish me luck!

BrianP

Hko 03-27-2009 08:24 PM

Quote:

Originally Posted by brianpbarnes (Post 3490042)
Hi,
I have spawned child processes by using the posix library, forking a forking fork, checking the return values, closing all files, cding to /, looking at getppid(), setsid(), etc. This seems like a microsofteanishly overly complicated, fork bomb generating way to send a commando on a mission.

This is about C I suppose?
Many systems, including Linux have the daemon() function:
Code:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

/* ... */

    if (daemon(0, 0) < 0) {
        perror("daemon() Failed");
        exit(1);
    }

Quote:

Originally Posted by brianpbarnes (Post 3490042)
Please ignore the weird icon).

I you go to the "advanced" message posting form there is a checkbox to disable smiley's.

brianpbarnes 03-28-2009 11:22 AM

How about an example of a functioning C daemon?
 
HKO,
While a dangling function without a caller can be of some interest, an apples to apples program which actually does something useful would be even more informative? What other infrastructure do you have to setup to use this? It would be cool to compare Perl to C on a line by line basis. How do you allocate, initialize, access and free elements of an associative array in C?

BrianP


All times are GMT -5. The time now is 09:16 PM.