[Ssh-sftp-perl-users] bind socket problem
Brought to you by:
dbrobins
From: <gd...@te...> - 2005-04-07 12:47:26
|
hello, I've been posting on nntp.perl.org in perl.beginners about a socket binding problem when trying to make several ssh connections on remote hosts, somebody told me about this list and suggested I should ask for your help. I'll copy&paste the discussion we had there my original post : I'm making a simple script that's supposed to update a certain number of boxes, spread around the area. my script is supposed to to connect to every hosts (via a file named "hosts") using ssh, launch wget to retrieve the patch update, and install it. Things work fine for the first host of the list. But can never get beyong that. I get a "Net::SSH: Can't bind socket to port 1023: Adresse déjà utilisée at ./test_ssh.pl line 46" message. my question is, how can I unbind the socket used by Net::SSH::Perl ? here's part of my code: use strict; use Net::SSH::Perl; my ($patchurl,$stout,$sterr,$exit,$ssh); my @ids = "$ENV{HOME}/.ssh/id_rsa"; my %params = ( 'protocol' => 2, 'identity_files' => \@ids, ); $patchurl = push @ARGV open HOSTS, "hosts" or die "je n'ai pas réussi à ouvrir le fichier hosts : $!"; while(<HOSTS>){ (...) $ssh = Net::SSH::Perl->new($_, %params); $ssh->login("root"); ($stout,$sterr,$exit) = $ssh->cmd("wget -q $patchurl"); (...) } responses : John Doe wrote: >> > I don't see the exact reason. But after having a look in the code >> > (Perl.pm, sub _create_socket, which tries ports from 1023 down to 512 to >> > bind to), maybe the ssh object is not destroyed between the loops. You >> > could try: >> > >> > ** define $ssh as my variable within the loop (not outside as currently) >> > ** put the code within the loop in a separate block, containing the >> > my-Definition of $ssh >> > ** use "undef $ssh" at the end of the loop (still within it of course) >> > ** Insert some diagnostic code at the beginning of the loop that >> > a) examines the $ssh object before the second "loop run" and/or >> > b) sleeps for e.g. a minute, so that you can look whats happening with >> > the bound port (netstat -neat from cmdline) >> > >> > I don't have the Modules installed, so I didn't made tests, sorry. >> > >> > joe > > > > I tried some of your recommendations, like declaring $ssh in the loop > and use "undef $ssh" at the end, but didn't solve the problem. > I did use netstat -neat during, and after the script launch. I didn't > see anything weird during the script running, I did see something > bizarre after : > > tcp 0 0 192.168.0.3:1023 192.168.0.1:22 > TIME_WAIT 0 0 > > that line, stayed there for at least a full minute before disappearing. > So I decided to add a 2min sleep at the end of the loop... and to my > surprise : IT WORKED! > I used netstat during the 2min sleep, it seems that the connection to > the 1023 socket lasts something between 1-2 minutes. > > It's weird, I wish there were another way around it. If anybody got an > explanation or a better solution about this "socket bind for more than a > minute, than just disappears" enigma, I'd be glad. This phenomen with the TIME_WAIT was my other thought to explain the behavior of your script, but then I decided not to mention it because I thought that the sub _create_socket code in Perl.pm will handle this: *---- code ----* sub _create_socket { my $ssh = shift; my $sock = gensym; my ($p,$end,$delta) = (0,1,1); # normally we use whatever port we can get ($p,$end,$delta) = (1023,512,-1) if $ssh->{config}->get('privileged'); # allow an explicit bind address my $addr = $ssh->{config}->get('bind_address'); $addr = inet_aton($addr) if $addr; ($p,$end,$delta) = (10000,65535,1) if $addr and not $p; $addr ||= INADDR_ANY; for(; $p != $end; $p += $delta) { socket($sock, AF_INET, SOCK_STREAM, getprotobyname('tcp') || 0) || croak "Net::SSH: Can't create socket: $!"; last if not $p or bind($sock, sockaddr_in($p,$addr)); if ($! =~ /Address already in use/i) { close($sock); next; } croak "Net::SSH: Can't bind socket to port $p: $!"; } if($p) { $ssh->debug("Allocated local port $p."); $ssh->{config}->set('localport', $p); } $sock; } *--- code ---* The code tries to bind to several ports (1023 down to 512). But now, when I look again - but still not deeply enough!... (and use the hint the port 1023 was also tried in the _second_ "loop run")... the code seems only to handle the "port already in use" case... Please look at the above code deeper... the croak code could be the problem, and a possibility could be not to croak so fast, but try port after port until binding has been done or the port range has fully be tested. I could have a deeper look myself tomorrow ...äh... après-midi, if you wish (we're located in the same time zone I think). btw - where are all the cracks who have the instant-shortestpossible-100%solution for all ??? greetings joe Thanks for your help |