I'm new to perl. I'd like to parse through a list of log files in a remote server(unix) probably around 200mb each to create a daily report.
What is the best way to read the log files from a remote server securely using ssh and efficiently.
Any pointer would be greatly appreciated.
Good Morning!
As already said in the comments there is no secret in it. I recommend you to use Net::SSH::Perl fo that kind of job:
#!/usr/bin/perl -w
use strict;
use lib qw("/path/to/module/");
use Net::SSH::Perl;
my $host = "hostname";
my $user = "username";
my $password = "password";
my $command = 'dir /var/log/'; #your command to read the directory
my $ssh = Net::SSH::Perl->new("$host", debug=>0);
$ssh->login("$user","$password");
my ($stdout,$stderr,$exit) = $ssh->cmd("$command"); #the standard outputs will be fetched
print $stdout; #obviously the STDOUT will be printed
For more informations about this Module you can read its documentation on CPAN: Net::SSH::Perl
I hope I could help you!
EDIT:
For sure you can run your script on the server and fetch its output in the same way. You just have to modify the $command. For example: $command: = "perl /home/$user/my_script.pl".
Related
First post, new to batch and scripting in general so please go easy on me.
I was tasked with writing a Perl script that would initiate SSH sessions with 6 phones and send them one CLI command to reboot them. Funny thing is, I know JACK about Perl. I do know a little batch automation and figured it'd be pretty simple to use plink to do what I needed. How wrong I was.
Here is an example of my plink batch.
#echo off
plink.exe -t -ssh XXXXXXX#111.111.1.1 -pw Abcd1234 < "C:\commands\commands.txt">output.txt
pause
Commands.txt:
debug
debug
reset hard
Running the batch file returns a cmd window displaying: Using Username "XXXXXXX"
And my output.txt shows:
debug
debug
reset hardsnoopyplus login:
It was at this point I realized I'd need some insight on how to service this second set of login credentials before sending my reset command.
Here we are at day 3 and my boss would like some results. I have about 4 broken iterations of my script and a good attitude. What can I try?
Also, here is a portion of a Perl script I found that claimed to be able to handle the snoopyplus debug login for cisco phones that I was unable to get working. The little bit of info I found told me to rewrite it in OpenSSH which I don't think is supported on Windows.
sub reboot{
my ($ip,$sshpassword,$sshusername,$debuglogin,$debugusername,$debugpassword,$debugprompt,$command) = #_;
print "\nPlease be patient whilst Cisco phone at address $ip is rebooted. This may take up to 90 seconds to complete...\n";
my $ssh = Net::SSH::Perl->new("111.111.1.1");
my $login_output = $ssh->login();
#my $ssh->login($sshusername, $sshpassword) || myAuditLog(LOG,"Login has failed. $!");
$ssh->waitfor('/'.$debuglogin.'>.*$/');
$ssh->send($debugusername);
$ssh->waitfor('/Password :.*$/');
$ssh->send($debugpassword);
$ssh->waitfor('/'.$debugprompt.'>.*$/');
$ssh->exec($command);
$ssh->close();
If you are on Windows, take a look at Net::SSH2, which comes included with Strawberry Perl. Using it, you should be able to talk to your IP phones:
#!perl
use strict;
use warnings;
use Net::SSH2;
my $ssh2 = Net::SSH2->new();
$ssh2->connect('example.com') or $ssh2->die_with_error;
if ($ssh2->auth_password($debuglogin, $debugpassword)) {
my $chan = $ssh2->channel();
$chan->shell();
while (!$channel->eof) {
if (my ($o, $e) = $channel->read2) {
$out .= $o;
$err .= $e;
} else {
$ssh2->die_with_error;
}
}
};
Try this format of plink command:
plink.exe -t -ssh -pw Abcd1234 -m "C:\commands\commands.txt" XXXXXXX#111.111.1.1 >output.txt
The script below functions just as intended. It calls the batch file which establishes a connection using PUTTY or scpecically psftp and transfers a handful of file. Once the transfer is complete i continue with the perl script to move the files to another directory.
My question is how could I capture an error from the PSFTP application? If there is an error xfering or establishing a connection i would like to generate a flag which then i could capture in perl and stop anything else from happening and send me an email. I just need guidance on generating the flag from the PSFTP application on error.
Thank you very much in advance!
My
use warnings;
use File::Copy;
my $TheInputDir = "//NT6/InfoSys/PatientSurvey/Invision/CFVMC/";
my $TheMoveDir = "//NT6/InfoSys/PatientSurvey/Invision/CFVMC/Completed";
system ('2166_PG_Upload_Batch.bat');
opendir (THEINPUTDIR, $TheInputDir);
#TheFiles = readdir(THEINPUTDIR);
close THEINPUTDIR;
#Get all the files that meet the naming convention
foreach $TheFile(#TheFiles)
{
if($TheFile =~ /2166/)
{
print "$TheFile\n";
move ("$TheInputDir$TheFile","$TheMoveDir");
}
}
You should read STDERR from your application into Perl. For that use Capture::Tiny
my ($stdout, $stderr, $exit) = capture {
system('2166_PG_Upload_Batch.bat');
};
#check for $stderr and do your stuffs i.e sending email etc
For more info refer perlfaq
I have two AIX hosts, both with same version of Perl installed (5.10.1), both with LWP::Simple module installed. I run a few Perl one-liners to download files from IBM's RAM.
They use LWP::Simple to first verify the module exists, then get the header for a resource (a file) at some URL to obtain file size, then finally download the file. It works fine on host #1, but on host #2 I get a couple different errors.
perl -e 'eval { require LWP::Simple; } or die 0;'
This one runs without issue on both. I've tested it dies as expected on a machine without LWP::Simple module installed.
perl -e 'use LWP::Simple; my #info = head("<URL here>"); die("-1 \$!") unless #info; print "$info[1]\n";'
On the problem host, I get "A file or directory in the path name does not exist" here, which I find weird given this is (I think?) a Unix error, but I can't reproduce this on the working host (#1) even by giving a garbage URL for this command.
perl -e 'use LWP::Simple; my $localfile = "<target file name here>"; my $url = "<URL here>"; my $status = getstore($url, $localfile); die "-1 \$!" unless is_success($status);'
Here I get a 501 error when I run on the problem host.
I reformatted these statements for clarity; it's actually invoked from a C# application via SSH.NET. Please pardon typos; the upshot is it works absolutely fine on AIX host #1 and not at all on AIX host #2.
Anyone have ideas how to further troubleshoot?
I am rather new in Perl. I have written a very simple script that copies and removes a file from sftp.
but the script should return some kind of output in order to integrate it with nagios.. using nsca or something.
the script is running on solaris 10.
here is the script:
#!/usr/bin/perl -w
use strict;
use warnings;
use Net::SFTP::Foreign;
use POSIX qw(strftime);
my $datestring =strftime "%d-%m-%Y", localtime;
my $host="sftp.mariog.com";
my $username="user";
my $local="/mnt/mariog";
my $file="BookingReport_Daily_$datestring.xls";
print "$file \n";
my $sftp = Net::SFTP::Foreign->new($host,
user => $username,
stderr_discard => 1,
autodie => 1,
);
$sftp->die_on_error("unable to establish SFTP Connection");
$sftp->get("$file", "$local/$file");
$sftp->remove($file);
$sftp->disconnect();
how to handle the fact that the file does not exist on the sftp? maybe it has not reached yet. there a daily file uploaded but at different times. the script is run by cron every 4 hours so most of the times it will not find files to transfer...
where can I get the output code of the transfer successful or not? so that i can pass it to a nagios passive check with nsca...
thank you for your help..
kind regards.
Mario
It looks like one way to check for a successful get in the documentation would be something like this:
$sftp->get("$file", "$local/$file") or die "get failed:" $sftp->error;
Heylo,
I'm experiencing, somewhat of, a conundrum regarding perl script development. I have written a small Perl script using the standard (basic) Perl installation. I have the following setup:
C:\MyScript\perl.pl
C:\MyScript\configuration\config.ini
C:\MyScript\output\output.txt
This is the perl.pl source:
$config = '/configuration/config.ini';
$conf = Config::IniFiles->new( -file => $config_file );
$output_dir = conf->val('output', 'out_dir');
$output_file = "$output_dir/output.txt";
open (out, ">$output_file") || die ("It's not your day mate!");
print out "This is a test...";
close out;
This is the config.ini contents:
[output]
output_dir = C:\MyScript\output
The problem I am having is that the second line ($conf) appears to be having trouble opening the file at that location. As I will be using this script in both a windows and unix environment (without installing any addition modules) I was wondering how I could get around this? What I was hoping was to create a script that would entirely configurable through the config.ini file. The config however, only works if I give it's absolute path, like so:
$config = 'C:\MyScript\configuration\config.ini';
But since this will be deployed to several diverse environments modifying the scripts source is out of the question. What would you guys recommend? How should one approach such a scenario?
Any help and/or advice is greatly appreciated.
All the best,
MC
The problem lies in the $config assignment line -
$config = '/configuration/config.ini';
This searches for config.ini from the root directory due to the leading '/', interpreting the path as an absolute rather than relative. Try changing it to
$config = './configuration/config.ini';
This though will only work if you execute the perl script from the 'MyScript' directory. Have a look at the FindBin module for such cases or you could manipulate the $0 variable to get your perl script path.
Here is a solution to allways know which is your current directory and use your other dirs
use strict;
use warnings;
use FindBin;
use File::Spec;
use Cwd;
BEGIN {
$ENV{APP_ROOT} = Cwd::realpath(File::Spec->rel2abs($FindBin::Bin)) ;
}
#now you know your script directory,
#no matter from where your script is called
#if you have Modules specific for your script which are in
#a dir "lib" in the same dir as your script is
use lib (
"$ENV{APP_ROOT}/lib",
);
my $config = $ENV{APP_ROOT} . '/configuration/config.ini';
#Here is your script
#...
$output_file = "$ENV{APP_ROOT}/$output_dir/output.txt";
All Modules are from the CORE distribution so you have them installed.
Note that Windows accepts "/" slashes, so you can use them there too.
Cheers.