Thread: [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 |
From: <gd...@te...> - 2005-06-13 15:24:46
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 hello, I've sent a mail to this list about two month ago, concerning a socket bind problem. I'm a bit surprised nobody got concerne about this problem, the first time, so I tought I might ask again. I made a script that connects to different computers via ssh. basically, all the computer's ip are in a file, my script reads the file, gets the ip adresse, connects via ssh, loops and get the next ip from the file. First connection works fine, but when it's time to connect to the next one, I get a message saying : Net::SSH:can't bind on socket to port 1023 when I do a netstat, I see the connection is up for about a minute then disappears. has anybody done a multi ssh connection script who hasn't come up with this problem ? 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"); (...) } -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.5 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFCraWFwU9DjvfD8u4RAjPvAJ9+PrXNwJoRfU63kJMtKdvM1lSOUgCfRI56 hKJkEMFqMj3QnjxTMaeV1oI= =EQSB -----END PGP SIGNATURE----- |
From: Robert L. <rla...@ao...> - 2005-04-07 15:21:05
|
On Thu, Apr 07, 2005 at 02:39:05PM +0200, guillaume dout=E9 wrote: > Things work fine for the first host of the list. But can never get=20 > beyong that. I get a "Net::SSH: Can't bind socket to port 1023: Adresse= =20 > d=E9j=E0 utilis=E9e at ./test_ssh.pl line 46" message. I had a similar problem with apache and net::sftp. I solved it by forcing the connection closed in SFTP.pm. > my question is, how can I unbind the socket used by Net::SSH::Perl ? Don't bother... Use fork. When the child process exits, the socket will (err... should) unbind. You might have to figure out how you're going to handle saving stdout, err, etc. I'd probably just write them to= =20 a log... >=20 > here's part of my code: >=20 > use strict; > use Net::SSH::Perl; >=20 > my ($patchurl,$stout,$sterr,$exit,$ssh); > my @ids =3D "$ENV{HOME}/.ssh/id_rsa"; >=20 > my %params =3D ( > 'protocol' =3D> 2, > 'identity_files' =3D> \@ids, > ); >=20 > $patchurl =3D push @ARGV >=20 > open HOSTS, "hosts" or die "je n'ai pas r=E9ussi =E0 ouvrir le fichier = hosts=20 > : $!"; >=20 > while(<HOSTS>){ >=20 > (...) if(fork) { # parent wait; } else { # child >=20 > $ssh =3D Net::SSH::Perl->new($_, %params); > $ssh->login("root"); > ($stout,$sterr,$exit) =3D $ssh->cmd("wget -q $patchurl"); } >=20 > (...) > } Good luck, Rob --=20 Robert Landrum Systems Programmer |
From: <gd...@te...> - 2005-04-08 13:14:08
|
Robert Landrum wrote: > > my question is, how can I unbind the socket used by > > Net::SSH::Perl ? > > > Don't bother... Use fork. When the child process exits, the > socket will (err... should) unbind. You might have to figure out > how you're going to handle saving stdout, err, etc. I'd probably > just write them to a log... > I made a stripped version of my script, so that it reflects the problem. I added your suggestions there, but the problem remain, I still have a Net::SSH: Can't bind socket to port 1023: Adresse déjà utilisée at ./test_ssh.pl line 46 message after the second run in the loop here is the full script : use strict; use Net::Ping; use Net::SSH::Perl; my ($p,$stout,$sterr,$exit,$cmd); my (@errping); open HOSTS, "hosts" or die "je n'ai pas réussi à ouvrir le fichier hosts!"; $p = Net::Ping->new("icmp"); my @ids = "$ENV{HOME}/.ssh/id_rsa"; my %params = ( 'protocol' => 2, 'identity_files' => \@ids, 'port' => 22, 'debug' => 1, ); while(<HOSTS>){ next if(/^(#|\s+#|\n)/); chomp; # ping test unless ($p->ping($_)) { print "ip : $_ \nerreur : pas de ping \n\n"; next; } #ssh connexion + wget print "téléchargement du fichier \n"; if (fork){ wait; } else{ my $ssh = Net::SSH::Perl->new($_, %params); $ssh->login("root"); ($stout,$sterr,$exit) = $ssh->cmd("wget -q http://www.google.com "); } } print "mise à jours des ipcops terminé\n"; |