Hi,

First off, this is my first posting on perlmonks and my first real perl script, so pls be gentle...

The script below is used to run multiple instances of the required command (ping, ssh, any function as reqd, but also uses sleep for testing) in a sub. To launch and manage/limit the instances running at any 1 time, I use fork and waitpid.

The input file is a plain text file containing hostnames. In the full script, the hostname is passed to the sub in question, but as this is not required for testing with sleep I have taken it out.

When I run the script with "for (<IN>)" the script works fine, but this will create a temp array (so I'm told). As the input file/list of hosts will run into the 1000's this will use memory where ideally it shouldnt. If I use "while (<IN>)" (which does not create a temp array/use memory), the script just loops the inputfile. It will run until you kill it, regardless of how many hosts are in the input file.

I'd like to do this cleanly with "while" rather than "for" if possible. Does anyone have any good/clean/noob friendly ideas? It may be easier to bite the bullet & use "for", but I thought I'd ask first...

perl version is 5.8.5

Regards
Paul

## Additional Info ##
Apologies for not including in original post:

The loop only occurs when the "waitpid" function is called. If the max number of runs is not met ($max=2 in example), the while finishes ok.

As such this may be a while/fork or waitpid issue.

#!perl -w use strict; use Data::Dumper; my $prog=$0; my ($estat,$infile,$errfile,$action,$sub,$thishost,$pid,$cpid,$pidstat +,$thiskey); my (%track,%closed); my $max=2; my $rcount=0; my $tcount=0; $infile=$ARGV[0]; open(IN,'<',$infile) || die "cannot open input file $infile \"$!\""; sub _sleep { sleep int(rand(10)); return $?>>8; } sub _waitpid { my $cpid=waitpid(-1,0); my $pidstat=$? >> 8; $closed{$track{$cpid}}=$pidstat; $rcount--; } #here while (<IN>) { #for (<IN>) { chomp; $rcount++; $tcount++; print "Progress: $tcount\r"; $pid = fork; if ($pid==0) { # child close IN; # start call sleep sub my $estat=_sleep; exit $estat; # end call sleep sub # start direct sleep #sleep int(rand(10)); #exit $?>>8; # end direct sleep } else { # parent $track{$pid}=$_; if ( $rcount >= $max ) { # start call waitpid sub _waitpid(); # end call waitpid sub # start direct waitpid #my $cpid=waitpid(-1,0); #my $pidstat=$? >> 8; #$closed{$track{$cpid}}=$pidstat; #$rcount--; # end direct waitpid } else { } } } print "\n\nWaiting for procs to finish...\n"; while ($rcount>0) { _waitpid(); } print "Done\n"; for $thiskey (keys %closed) { print "$thiskey $closed{$thiskey}\n"; } print Dumper(\%closed); close IN; print "End\n";

In reply to while/fork problem by hammopau

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.