Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Need advice on how to fork with intercommunication

by ewhitt (Scribe)
on Aug 05, 2007 at 10:33 UTC ( [id://630709]=perlquestion: print w/replies, xml ) Need Help??

ewhitt has asked for the wisdom of the Perl Monks concerning the following question:

I have a Perl script to telnet to a list of devices and gather data to put into a MySql database. This script takes a considerable amount of time to complete due to the number of devices. I would appreciate any advice / suggestions on how I could fork child process to parallel this. Also, being able to intercommunicate between the parent and child processes would be helpful (IPC ?). Thanks in advance!
  • Comment on Need advice on how to fork with intercommunication

Replies are listed 'Best First'.
Re: Need advice on how to fork with intercommunication
by clinton (Priest) on Aug 05, 2007 at 10:41 UTC
    Have a look at perlipc. And you could look on CPAN for IPC::Open2 which opens a process for reading and writing.

    Clint

Re: Need advice on how to fork with intercommunication
by NetWallah (Canon) on Aug 05, 2007 at 14:46 UTC
    The THREAD code below should get you started.

    Original attempt by me, but most credit goes to Browseruk.

    #! perl -slw use strict; use threads; use Thread::Queue; $| = 1; #$OUTPUT_AUTOFLUSH our $KIDS ||= 10; our $WORK ||= 500; our $SLEEP||= 5; sub kid { my( $Q ) = shift; my $tid = threads->tid; my $count=0; printf "Kid: %02d started\n", $tid; ## Pick a work item of the queue and process it while( my $work = $Q->dequeue ) { printf "Kid: %02d processing work item '%s'\n", $tid, $work; $count ++; ## Replace the sleep with the code to process teh work items rand > 0.7 and sleep rand( $SLEEP ); } print "kid: $tid ending after processing $count items.\n"; } ## A queue for communications my $Q = new Thread::Queue; ## Start the kids my @kids = map{ threads->create( \&kid, $Q ) } 1 .. $KIDS; ## Wait till they're all up and running sleep 1 until @{[ threads->list ]} == $KIDS; ## Feed the queue with work ## The limit just ensure we don't fill lots of memory for my $workitem ( 1 .. $WORK ) { sleep 1 while $Q->pending > $KIDS *10; print "Queueing work item $workitem"; $Q->enqueue( $workitem ); } ## Tell them to stop $Q->enqueue( (undef) x $KIDS ); ## And wait for them to do so. $_->join for @kids;
    This code has been posted to perlmonks a year or so ago, but I could not find the reference, and it was pretty short anyway.

         "An undefined problem has an infinite number of solutions." - Robert A. Humphrey         "If you're not part of the solution, you're part of the precipitate." - Henry J. Tillman

Re: Need advice on how to fork with intercommunication
by gryphon (Abbot) on Aug 05, 2007 at 14:50 UTC

    Greetings ewhitt,

    Forking is nice, but when I need data back to the parent, I like using threads instead. The communication between source and thread is simple, only once at the end, but it usually does what I need, and it's pretty intuative.

    If you need communication before the end of the thread, you can set that up with shared data structures with threads::shared.

    #!/usr/bin/perl use strict; use warnings; use threads; use IO::File; use Net::SSH 'sshopen2'; use DBI; # username@hostname connect strings my @servers = qw( gryphon@hornet gryphon@kursk gryphon@garfield ); # startup a thread for each server my @threads = map { threads->new( sub { my ($server) = $_[0]; my ( $reader, $writer ) = ( IO::File->new(), IO::File->new +() ); # ssh to the server and run "ls" sshopen2( $server, $reader, $writer, 'ls' ) or die "ssh fa +iled $!"; my @rv; while ( <$reader> ) { chomp(); push @rv, $_; } # return the server name and an array ref of filenames return $server, \@rv; }, $_, ); } (@servers); # usual DBI stuff my $dbh = DBI->connect( 'DBI:mysql:database=DATABASENAME;host=localhost;port=3306', 'USERNAME', 'PASSWORD', { 'RaiseError' => 1, 'AutoCommit' => 1 }, ) or die $DBI::errstr; my $sth = $dbh->prepare('INSERT INTO results (server, filename) VALUES + (?,?)'); # wait for threads to complete; insert data into db foreach (@threads) { my ( $server, $files ) = $_->join(); $sth->execute( $server, $_ ) foreach ( @{ $files } ); } $dbh->disconnect();

    gryphon
    Director Technology, Petfinder.com (Discovery Communications Inc.)
    code('Perl') || die;

Re: Need advice on how to fork with intercommunication
by perrin (Chancellor) on Aug 05, 2007 at 16:31 UTC
    Parallel::ForkManager makes it easy to manage a bunch of jobs in parallel. If you need more communication than you can get from exit codes, sharing through your MySQL database is a pretty simple way to do it. It has more overhead than local socket techniques, but is easier to get started with and less error-prone.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://630709]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2024-04-25 05:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found