my $SELECT = IO::Select->new(); my $forks = 100; sub portcheck { my ( $checknodes, $port, $forks, $longest, $verbose ) = @_; # Hashes to store results and good/bad arrays my ( %threads, %results, $pid, $node ); my ( @goodnodes, @badnodes ); # Set default port to 22 if ( !$port ) { $port = '22'; } # Destroyable copy of the list of nodes. my @checks = @{$checknodes}; # Set forks properly if ( !$forks ) { $forks = $fanout; } $forks = ( $forks > scalar @checks ) ? scalar @checks : $forks; # Fork initial threads for ( 1 .. $forks ) { forkportcheck( shift @checks, \%threads, $port ); } # Prepare to display results in order my $resindex = 0; # Wait for a process to complete while ( ( $pid = wait ) > 0 ) { # store result of the port check $results{ $threads{$pid} } = ( $CHILD_ERROR == 0 ); # delete the completed thread delete $threads{$pid}; # Fork a new thread if there are still nodes to run if ( scalar @checks ) { forkportcheck( shift @checks, \%threads, $port ); } no warnings 'uninitialized'; #store and print the results for completed threads while ( defined $results{ $checknodes->[$resindex] } ) { $node = $checknodes->[ $resindex++ ]; if ( $results{$node} ) { push @goodnodes, $node; if ($verbose) { printf {*STDERR} "%-${longest}s: ssh port check passed\n", $node; } } else { push @badnodes, $node; if ($verbose) { printf {*STDERR} "%-${longest}s: ssh port check failed\n", $node; } } } } if ($verbose) { say {*STDERR} q{}; } return ( \@goodnodes, \@badnodes ); } sub forkportcheck { my ( $node, $threads, $port ) = @_; # Ensure node is defined if ( !$node ) { return 0; } # Fork the process -- we just need the return code. my $pid = fork; if ( !defined $pid ) { croak "Fork didn't work $ERRNO"; } # is this the child if ( $pid == 0 ) { # Perform socket connection my $sock = IO::Socket::INET->new( PeerAddr => $node, Timeout => 1, PeerPort => $port, Proto => 'tcp', ); # Exit 0 if get a socket. Else exit 1 if ($sock) { close $sock or carp $ERRNO; exit 0; } exit 1; } # store the node name for the pid in the threads $threads->{$pid} = $node; return $pid; }