http://qs321.pair.com?node_id=269796

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

Monks,

I am trying to get Net::LDAP to allow me to send many queries to an LDAP database and return each one of the queries attributes and values to STDOUT as it runs.
Here is what I have tried so far and although it seems to be running every search query, it only writes to the screen the last query results.

For example, my macs.txt contains 10 Mac addresses. When they are sent to LDAP 1 at a time as you will see in the code below only the 10th MAC addresses attributes and values will be returned. Again my goal is to return all attributes and values from every query(all 10 macs).

I appreciate everyone's help. Here is the code.
use Net::LDAP; my $server = "192.168.0.20"; my $port = "389"; my $connection = Net::LDAP->new($server, port => $port) or die "Unable + to connect to $server:", @$, "\n"; $connection->bind() or die "could not bind: $@\n"; print "\n\nConnected to LDAP\n\n"; my @attrs = ['username', 'plan', 'ipaddress']; open MACS, "macs.txt" or die "Couldn't open the file or die: $!\n"; @macs = <MACS>; close MACS; print "Opened the Macs file\n"; my $count=0; foreach my $mac (@macs) { $count++; print "Processing: $count\n"; ldapsearch($mac); } sub ldapsearch { my $mac = shift; print "$mac\n"; my $searchobj = $connection->search( base => 'o=ldap, filter => "cn=$mac", attrs => @attrs, callback => \&callback, ); $searchobj->code && die $searchobj->error; } sub callback { my ($searchobj, $entry) = shift @_; $entry = $searchobj->shift_entry; if ($entry) { print $entry->dn, "\n"; print $entry->get_value('plan'); print $entry->get_value('ipaddress'); print $entry->get_value('username'); } }

Replies are listed 'Best First'.
Re: Net::LDAP doesn't return until end of loop
by lachoy (Parson) on Jun 28, 2003 at 16:14 UTC

    The docs say that the second object passed to the callback for a search will be an entry found:

    If the request is a search then multiple packets can be received from the server. Each entry is received as a separate packet. For each of these the subroutine will be called with a Net::LDAP::Entry object as the second argument.

    So I think the callback should look like this:

    sub callback { my ($searchobj, $entry) = @_; # note: no 'shift' if ($entry) { print $entry->dn, "\n"; print $entry->get_value('plan'); print $entry->get_value('ipaddress'); print $entry->get_value('username'); } else { warn "No entry passed in for callback...\n"; } }

    This will at least let you know that your callback is being called the appropriate number of times.

    Chris
    M-x auto-bs-mode

      I changed my callback to be without the shifting of entry. What happens is all looped data including the 10th mac address return "No entry passed...", however the 10th also returns the values from ldap that were queried for. This doesn't make any sense because its acting like for the first 9 Mac's no entry is passed, this I believe, but then on the 10th, no entry is passed, but data is returned ?!? Please advise.

        Two things: First, you probably want to pass \@attrs or [ @attrs ] instead of what you've got. You might also need to set scope => 'sub' in the search attributes.

        Second, I'd try a different strategy, using this idiom to run through the results of a search:

        my $ldap_msg = $ldap->search( ... ); if ( my $code = $ldap_msg->code ) { die "Error running search: ", Net::LDAP::Util::ldap_error_text( $code ); } while ( my $entry = $ldap_msg->shift_entry ) { # use $entry }

        It's been a while since I used LDAP and I just cribbed this from SPOPS::LDAP, which I wrote when I was using LDAP :-)

        Chris
        M-x auto-bs-mode

Re: Net::LDAP doesn't return until end of loop
by archon (Monk) on Jun 28, 2003 at 03:35 UTC
    hmm, hard to say given the information. have you tried with just one mac address? what does your data look like? i notice you're not chomping the $mac. also, you have: my @attrs = ['username', 'plan', 'ipaddress']; when i think you want $attrs. (same in ldapsearch). does it print the $mac each time for $ldapsearch? try putting an else in the callback that prints something.. perhaps it's just not getting an entry for some reason. HTH