CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Help needed for my script

 

First page Previous page 1 2 Next page Last page  View All


richsark
User

Apr 21, 2009, 6:46 AM

Post #1 of 26 (6115 views)
Help needed for my script Can't Post

I have this code:






Code
   

#!/usr/bin/perl

use strict;

use warnings;

use Net::SSH::Expect;



open(my $out, "log.txt") or die "Could not open log: $!\n";



##### Step 1, read subnet.txt

open(my $in, "<subnet.txt") or die "Could not open subnet.txt: $!\n";

while(<$in>) {

chomp;



##### Step 2: run getzoneprof, and keep first 4 lines only

my @getzoneprof = `getzoneprof -u Xxx -p Xxx -a $_ -o Orig`;

@getzoneprof = @getzoneprof[0..3];



##### Find server name

warn "Server not found for $_\n",next unless $getzoneprof[-1] =~ /dnsServers=(\S+)/;

my $dns = $1;



##### ssh to server

my $ssh = Net::SSH::Expect->new (

host => $dns,

password=> '12345',

user => 'richsark',

);



my $login_output = $ssh->login();

unless($login_output =~ /Last Login/) {

warn "Login has failed. Login output was $login_output";

next;

}



##### run ls to look for files

my $ls = $ssh->exec("ls /opt/rich/sark/*.jnl");

$found='no';

$found='yes' if $ls =~ m|/opt/rich/sark/|;

print $out "From zone $_ containing dnsserver \"$dns\" found=$found of presense of \"jnl\" files\n";



$ssh->close;

}



close($out);



I have 3 issues that I need help with,

1. the script is only seeing 1 dns server from dnsServers= line

2. If a dns server is repeated, there is not need to ssh to it agian

3. when I ssh, the sessions remains open, so after 4 logins, I cant login anymore, but I think that can be fixed if we can solve issue 2.





Thanks


1arryb
User

Apr 21, 2009, 7:17 AM

Post #2 of 26 (6112 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Hi Rich,

1. We can't help you with the file parse unless you post a sample of your input data.

2. To avoid ssh'ing to a host twice, add a little hash of "seen" hostnames:

Code
... 
open (...);
my $seen_hosts = {};
while(<$in>) {
...
next if exists($seen_hosts->{$dns});
$seen_hosts->{$dns} = 1;
...
}

3. This loop can abort an iteration without closing the ssh session. Try:

Code
... 
unless($login_output =~ /Last Login/) {
warn "Login has failed. Login output was $login_output";
$ssh->close;
next;
}
...


Cheers,

Larry


richsark
User

Apr 21, 2009, 7:24 AM

Post #3 of 26 (6110 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

Hi, Thanks for your reply, the sample data from subnet.txt looks like

10.2.0.0/16
10.2.92.0/24
10.3.0.0/16

I need to run a cli that points to each of the contents in subnet.txt and run it one subnet at a time, like so

getzoneprof -u Xxx -p Xxx a $subnet -o Orig

Once you run this I get lots of stuff, but I am only interested in on a few parameters which start from the first 4 lines of the output.

This is what it looks like:

getzoneprof -u XxX -p XxX -a 10.0.0.0/16 -o Orig

Zone=10.0.0.0/16
ParentAddress=10.0.0.0/8
NetworkAddress=10.0.0.0
dnsServers=richm01.cmmc.sark.com P 0,hhyt.sark.com 0,6cnscuyt1.netdevice.richsark.com S 0, dell.netdevice.rich.net S 0, sony123.sarkie.west.org S 0

I need to ssh to each and every server listed in the dnsServers= line and see if there are *.jnl files present. If so I report on it.

Does this help in solving my code?


(This post was edited by richsark on Apr 21, 2009, 7:33 AM)


1arryb
User

Apr 21, 2009, 8:04 AM

Post #4 of 26 (6101 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Hi Rich,

You only get the first host from the dnsServers line because that's what you asked for! The regular expression '/dnsServers=(\S+)/' is only looking for the first sequence of non-whitespace characters from the line. Better would be:

Code
... 
##### Parse hostnames from the dnsServers line.
my $serverLine = $getzoneprof[-1];
# You should check that $getzoneprof[-1] actually contains a dnsServers line here.
$serverLine =~ s/dnsServers=//; # Remove the prefix.
my @servers = ();
foreach my $token (split(/,/, $serverLine)) { #split the server line on the commas.
$token =~ /(\S+)/; # Look for the first "word" of the token.
push (@servers, $1) if $1;
}
# You should also check that you got at least 1 server here.
foreach my $dns (@servers) {
# Do something with the dns server.
}


UPDATE: Bugs fixed in the original are marked as bold.

Cheers,

Larry


(This post was edited by 1arryb on Apr 21, 2009, 8:58 AM)


richsark
User

Apr 21, 2009, 8:27 AM

Post #5 of 26 (6095 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

Hello, I added your code to my code, but I get an error:

syntax error at test.pl line 22, near ") {"
Bad name after '12345' at test.pl line 35

I am not an expert in perl, so I would appericate any help in corrections


Code
  

#!/usr/bin/perl

use strict;

use warnings;

use Net::SSH::Expect;



open(my $out, "log.txt") or die "Could not open log: $!\n";



##### Step 1, read subnet.txt

open(my $in, "<subnet.txt") or die "Could not open subnet.txt: $!\n";

while(<$in>) {

chomp;



##### Step 2: run getzoneprof, and keep first 4 lines only

my @getzoneprof = `getzoneprof -u Xxx -p Xxx -a $_ -o Orig`;

@getzoneprof = @getzoneprof[0..3];



##### Parse hostnames from the dnsServers line.

my $serverLine = $getzoneprof[-1];

# check that $getzoneprof[-1] actually contains a dnsServers line here.

$serverLine =~ s/dnsServers=//; # Remove the prefix.

my @servers = ();

foreach my $token (split(/,/, $1) { #split the server line on the commas.

$token =~ /(\S+)/'; # Look for the first "word" of the token.

push (@servers, $1) if $1;

}



# You should also check that you got at least 1 server here.

foreach my $dns (@servers) {

}


##### ssh to server

my $ssh = Net::SSH::Expect->new (

host => $dns,

password=> '12345',

user => 'richsark',

);



my $login_output = $ssh->login();

unless($login_output =~ /Last Login/) {

warn "Login has failed. Login output was $login_output";

next;

}



##### run ls to look for files

my $ls = $ssh->exec("ls /opt/rich/sark/*.jnl");

$found='no';

$found='yes' if $ls =~ m|/opt/rich/sark/|;

print $out "From zone $_ containing dnsserver \"$dns\" found=$found of presense of \"jnl\" files\n";



$ssh->close;

}



close($out);




1arryb
User

Apr 21, 2009, 8:50 AM

Post #6 of 26 (6085 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Hi Rich,

You caught me! I was too lazy to download Net::SSH::Expect so I could test my code. I fixed the typos in my reply above (look at the bolded lines).

However, the modified program you posted won't do what you want even after you fix the compile errors: Every thing from line 55 down should be inside the "foreach my $dns (@servers) {}" interior loop.

Cheers,

Larry


FishMonger
Veteran / Moderator

Apr 21, 2009, 8:56 AM

Post #7 of 26 (6083 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

Shouldn't
foreach my $token (split(/,/, $1)) { #split the server line on the commas.

be:
foreach my $token (split(/,/, $serverLine)) { #split the server line on the commas.


1arryb
User

Apr 21, 2009, 8:57 AM

Post #8 of 26 (6080 views)
Re: [FishMonger] Help needed for my script [In reply to] Can't Post

Yup. Fixed.


richsark
User

Apr 21, 2009, 8:58 AM

Post #9 of 26 (6079 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

Hi Sir,

I will correct as you stated. Is there a way you can help me understand what you ment on "55 down should be inside the "foreach my $dns (@servers) {}" interior loop. "

So you mean I take my stuff and paste it there. I wouldnt mind a revised code, so its not all over the place.

Thanks


1arryb
User

Apr 21, 2009, 9:17 AM

Post #10 of 26 (6071 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Hi Rich,

Here you go. This program compiles cleanly, but is untested.

Code
#!/usr/bin/perl 

use strict;
use warnings;

use Net::SSH::Expect;

open(my $out, "log.txt") or die "Could not open log: $!\n";

##### Step 1, read subnet.txt
open(my $in, "<subnet.txt") or die "Could not open subnet.txt: $!\n";

# Keep track of hosts we've seen before.
my %seenHosts;

while(my $zone = <$in>) {
# In long loops it's better to read <$in> to a local variable instead of relying on $_.
chomp($zone);

##### Step 2: run getzoneprof, and keep first 4 lines only
my @getzoneprof = `getzoneprof -u Xxx -p Xxx -a $zone -o Orig`;
@getzoneprof = @getzoneprof[0..3];

##### Parse hostnames from the dnsServers line.
my $serverLine = $getzoneprof[-1];

# check that $getzoneprof[-1] actually contains a dnsServers line here.
unless ( $serverLine =~ /dnsServers/ ) {
print "Can't get a dnsServers line from getzoneprof -a $zone\n";
next;
}

$serverLine =~ s/dnsServers=//; # Remove the prefix.

my @servers = ();
foreach my $token (split(/,/, $serverLine)) { #split the server line on the commas.
$token =~ /(\S+)/; # Look for the first "word" of the token.
push (@servers, $1) if $1;
}

unless (scalar(@servers)) {
print "Can't parse a dns server from \"dnsServers=$serverLine\"\n";
next;
}

foreach my $dns (@servers) {
next if exists($seenHosts{$dns});
$seenHosts{$dns} = 1;

##### ssh to server
my $ssh = Net::SSH::Expect->new (
host => $dns,
password=> '12345',
user => 'richsark',
);

my $login_output = $ssh->login();
unless($login_output =~ /Last Login/) {
warn "Login has failed. Login output was $login_output";
# Make sure we close the ssh session if we abort the loop.
$ssh->close;
next;
}

##### run ls to look for files
my $ls = $ssh->exec("ls /opt/rich/sark/*.jnl");
my $found='no';
$found='yes' if $ls =~ m|/opt/rich/sark/|;

print $out "From zone $zone containing dnsserver \"$dns\" found=$found of presense of \"jnl\" files\n";

$ssh->close;
}

}

close($out);


Cheers,

Larry


(This post was edited by 1arryb on Apr 21, 2009, 9:21 AM)


richsark
User

Apr 21, 2009, 9:35 AM

Post #11 of 26 (6066 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

HI Larry, thanks, looks like the dnsServers= line are being put in one line: so I think that is translating to one long DNS server name :) when there are 5

1vidrnssm01.cmmc.sark.comdnssm.sark.comdnsdl.sark.comdnsrdc02.netdevice.richsark.commcc-nsco01.ny.sarkie.net


1arryb
User

Apr 21, 2009, 9:37 AM

Post #12 of 26 (6064 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Rich,

Add a line to print the full dnsServers line. Are the server entries separate by something other than a comma? If so, you may need to adjust the regex in the split command.

Larry


richsark
User

Apr 21, 2009, 9:44 AM

Post #13 of 26 (6062 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

Hi,

They look like this:

dnsServers=richm01.cmmc.sark.com P 0,hhyt.sark.com 0,6cnscuyt1.netdevice.richsark.com S 0


Thanks Larry


1arryb
User

Apr 21, 2009, 10:10 AM

Post #14 of 26 (6057 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Rich,

The commas are there; the split() should have worked. To debug, add more debug print statements (one that prints each server as it is parsed from the line would be good). Or you could use the perl debugger (try "perldoc perldebug" from the command line) and step through the code.

Good luck,

Larry


richsark
User

Apr 21, 2009, 10:36 AM

Post #15 of 26 (6055 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

ok Larry will do !

Question, how hard is it to allow this script to continue if it cant successfully ssh into a server. Right now the script dies if I cant login in.

Will that be in your relem to help me :)

Thanks


1arryb
User

Apr 21, 2009, 10:51 AM

Post #16 of 26 (6054 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Rich,

Really? Are you sure it's dying or is it just finishing the server list w/o doing anything? If it's really dying, that could be because one of the $ssh methods is throwing an exception. To make sure this isn't the case, try enclosing the login in an eval block:

Code
... 
my $login_output;
eval {
$login_output = $ssh->login();
unless($login_output =~ /Last Login/) {
# The die will be caught in the if ($@) {} block, below.
die "Login output was $login_output";
}
};
# Capture "normal" login errors + $ssh method exceptions.
if ($@) {
print "\$ssh->login() failed: $@\n";
$ssh->close();
next;
}
...


Larry


richsark
User

Apr 21, 2009, 12:16 PM

Post #17 of 26 (6048 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

Hi Larry, I am sure it fails since I tried to manully SSH. Looks like some servers my password/token does not work. So if you could please add the code where it will skip the ones that I cant ssh to as well as perhaps log that server that failed so I know that it needs special attention.

Will that be ok?

Thanks


1arryb
User

Apr 21, 2009, 12:24 PM

Post #18 of 26 (6047 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Rich,

We've already wrapped the login with eval. If the login fails, the program executes 'next;' which should take you to the next loop iteration (i.e., next dns server), NOT exit.

Here is your next assignment: Start putting in diagnostic print statements (e.g. "Got here: 1", "Got here: 2", etc.) until you find out exactly what statement, if any, is causing your program to exit. Make sure you add one at the bottom of the program so you'll know if you get to the end.

Please post your instrumented code as well as the full program output.

Larry


richsark
User

Apr 22, 2009, 6:50 AM

Post #19 of 26 (6038 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

Hi Larry, Would you be able to assit me with this assigment. I am still very wet behind the ears and dont fully understand.

Thanks


1arryb
User

Apr 22, 2009, 10:43 AM

Post #20 of 26 (6024 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Rich,

Sorry, that's not how we play the game here Sly. I'm not going to write this program for you (much). Besides, I don't have the right dns setup here to run your program.

But don't panic! I'm not asking for the moon. Just put a print statement before and after each call to one of the ssh methods in your program, plus one at the start and end of the program. You can do that, can't you? Then, run the program, and post the code (with the print statements) and the program results.

Cheers,

Larry


richsark
User

Apr 23, 2009, 6:20 AM

Post #21 of 26 (6003 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

Hello Larry, sorry for the delay, I was in self pity for a bit but I am back. When I put the ssh login in without eval mode Looks like it works ok, as you can see I don’t have access to several servers on Asia or EMEA. I expected the script to continue like it has been, but as you can see I get a time out



I got lots of updates, and I am sorry if its long.



Non-Eval Mode:



ls-2: found=no

init: found=no

ls-1: found=yes

ls-2: found=yes

Could not login to irprns711b.ny.rich.com

Could not login to proxys77.ny.rich.com

init: found=no

ls-1: found=no

ls-2: found=no

Could not login to gadns01.ct.sg.criche.com

Could not login to gdns03.ct.sg.criche.com

Could not login to xp0124.ssh.hk.sarkie.com

Could not login to hxp0125.ssh.hk.sarkie.com

Could not login to kxp0426.ssh.hk.sarkie.com

Could not login to kkxp6127.sly.hk.sarkie.com

Could not login to srbdns01.ct.sg.criche.com

Could not login to tjp-dns-04.tk.jp.criche.com

Could not login to tlp-dns-05.tk.jp.criche.com

SSHAuthenticationError Login timed out. The input stream currently has the contents bellow: at /usr/lib/perl5/site_perl/5.10/Expect.pm line 828



When I put in eval mode, I get different responses:



$ perl test3.pl



init: found=no

ls-1: found=no

ls-2: found=no

init: found=no

ls-1: found=no

ls-2: found=no

init: found=no

ls-1: found=no

ls-2: found=no

$ssh->login() failed: Login output was

richsark's Password: at test3.pl line 43, <$in> line 1.



init: found=no

ls-1: found=no

ls-2: found=no

init: found=no

ls-1: found=no

ls-2: found=no

init: found=no

ls-1: found=no

ls-2: found=yes

init: found=no

ls-1: found=yes

ls-2: found=yes

init: found=no

ls-1: found=yes

ls-2: found=yes

$ssh->login() failed: Login output was

Total users logged in under your name (via BoKS): 4 (1 on this host)

Total users logged in (via BoKS): 14783 (1 on this host)

Last Login 04/23/09 09:07:52 - 04/23/09 09:08:27 (inpdns111a.ky.sarkie.com:pts/1)



****** BoKS 6.5 ******

Last login: Thu Apr 23 08:37:32 2009 from 10.129.148.48

Could not chdir to home directory /home/richsark: No such file or directory

$ at test3.pl line 43, <$in> line 5.



$ssh->login() failed: Login output was

Total users logged in under your name (via BoKS): 4 (1 on this host)

Total users logged in (via BoKS): 14785 (1 on this host)

Last Login 04/23/09 09:08:29 - 04/23/09 09:08:44 (inpdns111b.ny.sarkie.com:pts/1)



****** BoKS 6.5 ******

Last login: Thu Apr 23 08:37:50 2009 from 10.129.148.48

Could not chdir to home directory /home/richsark: No such file or directory

$ at test3.pl line 43, <$in> line 5.



init: found=no

ls-1: found=yes

ls-2: found=yes

$ssh->login() failed: Login output was

richsark's Password: at test3.pl line 43, <$in> line 70.



The script still continues…..



But.. there are some servers that have a different prompt versus the original we have in place.

some servers when I SSH to have this senerio which I have to type in "yes" to continue:



Could not create directory '/home/richsark.ssh'.
The authenticity of host 'sarkie.ky.sarfish.com (19.97.6.15)' can't be established
RSA key fingerprint is 96:42:39:ff:a4:3c:1a:17:7d:5b:7e:a4:8a:b7:3d:51.
Are you sure you want to continue connecting (yes/no)? yes
Failed to add the host to the list of known hosts (/home/richsark/.ssh/known_hosts).



How can we had this to the script to allow such scenario, That may solve some of my login problems, but I think there me another underlying issue under the radar.



This is my latest code:




Code
   

#!perl

use strict;

use warnings;

use Net::SSH::Expect;



open(my $out, ">log.txt") or die "Could not open log: $!\n";



my %Processed;



##### Step 1, read subnet.txt

open(my $in, "<subnet.txt") or die "Could not open subnet.txt: $!\n";

while(<$in>) {

chomp;



##### Step 2: run getzoneprof, and keep first 4 lines only

my @getzoneprof = `./richsark-getzoneprof.exe -u xXx-p XxX -a $_ -o Sark1`;

@getzoneprof = @getzoneprof[0..3];



##### Find server name

warn "Server not found for $_\n",next unless $getzoneprof[-1] =~ /dnsServers=(.+)/;

my $dns_line = $1;

my @dns = grep {length($_)>1} split(/[\s,]+/, $dns_line);



foreach my $dns (@dns) {

print next if $Processed{$dns};

$Processed{$dns} = 1;



##### ssh to server

my $ssh = Net::SSH::Expect->new (

host => $dns,

password=> '12345',

user => 'rich',

raw_pty => 1,

timeout => 10



);



my $login_output;

eval {

$login_output = $ssh->login();

unless($login_output =~ /IT IS AN OFFENSE TO CONTINUE/) {

# The die will be caught in the if ($@) {} block, below.

die "Login output was $login_output";

}

};

# Capture "normal" login errors + $ssh method exceptions.

if ($@) {

print "\$ssh->login() failed: $@\n";

$ssh->close();

next;

}





##### run ls to look for files

my $found='no';

print "init: found=$found\n";

my $ls = $ssh->exec("ls /opt/richsark/named/*.jnl");

$found='yes' if($ls and $ls =~ m|/opt/richsark/named/|);

print "ls-1: found=$found\n";

$ls = $ssh->exec("ls /opt/richsark/named/sec_richsark/*.jnl");

$found='yes' if($ls and $ls =~ m|/opt/richsark/named/sec_richsark/|);

print "ls-2: found=$found\n";



print $out "From zone $_ containing dnsserver \"$dns\" found=$found of presense of \"jnl\" files\n\n";



$ssh->close;

}

}



close($out);








1arryb
User

Apr 23, 2009, 11:37 AM

Post #22 of 26 (5991 views)
Re: [richsark] Help needed for my script [In reply to] Can't Post

Hi rich,

Good news! ssh->login() is not throwing an exception. All of the problems are normal login failures to the remote host. That means that the eval {} block around the login isn't necessary (but you still have to process login's output).

Looking at your program's output, I see 3 reasons your logins are failing:

1. "Could not chdir to home directory /home/richsark: No such file or directory" This means that the richsark user doesn't have a home directory setup on that host. Talk to the system administrator and have him or her create one for you.

2. "richsark's Password:" The user/password you used was rejected by the server. Again, talk to the sysadmin for the host and get that fixed. UPDATE: Another possibility is that the remote host requires a carriage return or something before you get to the login prompt.

Both of the above problems are easiest debugged by ssh'ing from the command line (preferably with the remote administrator on the phone!).

The remaining problems are all about a mismatch between what Expect expected to happen during the login session and what really happened. Basically, you are going to have to "expect" the prompt to enter "yes" (or whatever). If you get it, your script will have to send the proper response. RTM for Expect (I'm sure there's an Expect forum somewhere out there, too). I'm no expert.

Good luck,

Larry


(This post was edited by 1arryb on Apr 23, 2009, 11:38 AM)


richsark
User

Apr 24, 2009, 5:25 AM

Post #23 of 26 (5984 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

Thanks Larry !

Your right, some servers I do not have access to since they are in another region. I just wanted to log those.

I will check out the the expect manual and see if I can add that variable.

Thanks for your help and guidence !


ace9006
New User

Dec 16, 2009, 4:49 AM

Post #24 of 26 (5858 views)
Re: [1arryb] Help needed for my script [In reply to] Can't Post

larrry,

what happens if my system dose not give a prompt ?

i try to login to a system that throws me directly to an application and dose not give a prompt. the result is that the login process of ssh::expect dose not finish and just hangs there till i kill the ssh process manually.

when i login to systems that give out a prompt i have no problem


1arryb
User

Dec 16, 2009, 7:38 AM

Post #25 of 26 (5853 views)
Re: [ace9006] Help needed for my script [In reply to] Can't Post

Hi ace,

It sounds like the standard ssh port (22) on that machine or on the firewall router at the remote site is configured to "tunnel" to a different program other than /bin/login. I'd have to look at their setup to say more. However, for you the solution is simple! Contact the Sysadmin of the remote system and explain your problem. If you have a legitimate need for shell access to their system, the admin will either fix the port configuration or work out a different protocol that gets you in. Otherwise, they'll tell you to take a hike :)

Cheers,

Larry

First page Previous page 1 2 Next page Last page  View All
 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives