Simple perl program failing to execute - perl

Here is a sample that fails:
#!/usr/bin/perl -w
# client.pl
#----------------
use strict;
use Socket;
# initialize host and port
my $host = shift || 'localhost';
my $port = shift || 55555;
my $server = "10.126.142.22";
# create the socket, connect to the port
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
or die "Can't create a socket $!\n";
connect( SOCKET, pack( 'Sn4x8', AF_INET, $port, $server ))
or die "Can't connect to port $port! \n";
my $line;
while ($line = <SOCKET>) {
print "$line\n";
}
close SOCKET or die "close: $!";
with the error:
Argument "10.126.142.22" isn't numeric in pack at D:\send.pl line 16.
Can't connect to port 55555!
I am using this version of Perl:
This is perl, v5.10.1 built for MSWin32-x86-multi-thread
(with 2 registered patches, see perl -V for more detail)
Copyright 1987-2009, Larry Wall
Binary build 1006 [291086] provided by ActiveState http://www.ActiveState.com
Built Aug 24 2009 13:48:26
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
While I am running the netcat command on the server side. Telnet does work.

The problem is that the pack template Sn4x8 is in error — and shouldn't be used in the first place. Something like pack_sockaddr_in($port, inet_aton($server)) as documented in Socket would be more likely to work.
But ideally, you wouldn't use the low-level Socket code at all. Here's a nicer bit of code that does it using IO::Socket, which is also a core part of perl for the past 15 years:
use strict;
use IO::Socket::INET;
my $host = shift || 'localhost'; # What is this here for? It's not used
my $port = shift || 55555;
my $server = "10.126.142.22";
my $socket = IO::Socket::INET->new(
PeerAddr => $server,
PeerPort => $port,
Proto => 'tcp',
) or die "Can't connect to $server: $#";
while (my $line = <$socket>) {
print $line; # No need to add \n, it will already have one
}
close $socket or die "Close: $!";

Works like this for me:
connect( SOCKET, pack( 'S n a4 x8', AF_INET, $port, $server))
or die "Can't connect to port $port! \n";
I think your original script AF_INET is unicode or something. If you delete the A and write again it works.

This is the line that make the packing work:
connect( SOCKET, pack( 'SnC4x8', AF_INET, $port, split /\./,$server ))
or die "Can't connect to port $port! \n";

Related

Perl socket, HP comware router

I'm trying to create a script in Perl that does the following
On a Windows 2008 R2 server, connects to a local OpenWRT router.
Send some commands to the router and save the output (interface brief)on a varaible
Edit the content of the variable (to keep the IP only)
Send the variable again to the router withinin another command
I created a socket but i dont seem to get any luck sending commands to the router. I'm not even sure if I'm logging in.
Here is my code:
use IO::Socket;
use strinct;
use warnings;
$iaddr = gethostbyname("192.168.1.237");
$ssh_port = 22;
$sin = sockaddr_in($ssh_port, $iaddr);
socket(DEV, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
connect(DEV, $sin) || die "Can't connect to EN4000: $!\n";
print DEV "user\n";
print DEV "password\n";
print DEV "echo test >> /etc/config/networkTest \n";
I run it, check the file /etc/config/networkTest but no modification is made
Have a look at Net::SSH::W32Perl
Here's a quick example;
#!/usr/bin/env perl
use strict;
use warnings;
use Net::SSH::W32Perl;
my $host='example.com';
my $user='john';
my $pass="pass";
# Connect
my $ssh = Net::SSH::W32Perl->new($host);
$ssh->login($user, $pass);
# Run command
my $cmd = q(echo test >> /etc/config/networkTest);
my($stdout, $stderr, $exit) = $ssh->cmd($cmd);

How can I check which method of checking a port state is more efficient?

I'm writing a script to schedule port checks on some of my servers, and report the state. I am planning to go along with one of two options:
Pipe the output of netcat (nc) into a perl variable, and check the return state
my $rcode=`nc -z 6.6.6.6 80; echo $?`
Use the perl module IO::Socket::PortState to do the same thing.
use IO::Socket::PortState qw(check_ports);
my %porthash = ( ... );
check_ports($host,$timeout,\%porthash);
print "$proto $_ is not open ($porthash{$proto}->{$_}->{name})
if !$porthash{$proto}->{$_}->{open};
I'd like to go along the more efficient (shorter time, more specific) route.
Is there a rule of thumb regarding this? As in piping the output of a system command/unix utility is more/less efficient than using a perl module? Or are different perl modules different, and one can check the same only by setting up multiple iterations of these checks and compare the time taken by this versus a system call to execute a unix utility?
This isn't really an answer to your question so much as a suggested implementation.
Just a quick run at an untested example of using Socket.pm.
This is probably the fastest perl implementation. But at the point you are using socket.pm you may as well just write it in C with socket.h. They are a near 1:1 mapping.
Ref:
#!/usr/bin/perl -w
use Socket;
$remote = $ARGV[0];
$port = $ARGV[1];
print ":: Attempting to connect to - $remote.\n";
$iaddr = inet_aton($remote) or die "Error: $!";
$paddr = sockaddr_in($port, $iaddr) or die "Error: $!";
$proto = getprotobyname('tcp') or die "Error: $!";
socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die "Error: $!";
connect(SOCK, $paddr) or die "Error: $!";
print ":: Connected Successfully!\n";

Why are MD5 hashes for the same data different on Linux and Windows?

Here's the workflow.
Client uploads an XML file and a checksum MD5 file to our FTP.
The Perl server copies the file from the FTP server.
The Perl server runs its own MD5 check on the XML file and then compares it to the value in the MD5 file.
The two MD5 hashes never match. But, when I copy the XML file to my windows machine and run the same Perl script running in Windows, I get the same answer as their MD5 file.
Can anyone tell me what’s going on?
Here’s the script I am using to compute the MD5 hash.
use warnings;
use strict;
use Digest::MD5;
my $fname = "MarketPricePoint_2013_07_16_1500.xml";
open (my $fh, '<', $fname) or die "Can't open '$fname': $!";
binmode ($fh);
my $hash = Digest::MD5->new->addfile($fh)->hexdigest;
print $hash;
ASCII mode is a common default for FTP servers that performs silent translation of line endings. If always transferring in binary mode is not an option, consider normalizing the line endings, as in the following.
use strict;
use warnings;
use Digest::MD5;
my $fname = "MarketPricePoint_2013_07_16_1500.xml";
open (my $fh, '<', $fname) or die "$0: open $fname: $!";
binmode ($fh) or die "$0: binmode: $!";;
(my $data = do { local $/; <$fh> }) =~ s/\r\n/\n/g;
my $hash = Digest::MD5->new->add($data)->hexdigest;
print $hash, "\n";

Perl - How to send a binary (image) file to a remote host from "master" host and create directory structure too?

I have done a bunch of reading and some testing to no avail.
I found this script here on stackoverflow which guided me in the right direction but, my abilities are inadequate to modify and fully understand for my needs.
#! /usr/bin/perl
use warnings;
use strict;
use File::Basename;
use File::Copy;
use File::Spec::Functions qw/ abs2rel catfile /;
use Net::SSH qw/ sshopen3 /;
my $HOST = "user\#host.com";
my $SRC_BASE = "/tmp/host";
my $SRC_FILE = "$SRC_BASE/a/b/c/file";
my $DST_BASE = "/tmp/dest";
system("md5sum", $SRC_FILE) == 0 or exit 1;
my $dst_file = catfile $DST_BASE, abs2rel $SRC_FILE, $SRC_BASE;
my $dst_dir = dirname $dst_file;
sshopen3 $HOST, *SEND, *RECV, *ERRORS,
"mkdir -p $dst_dir && cat >$dst_file && md5sum $dst_file"
or die "$0: ssh: $!";
binmode SEND;
copy $SRC_FILE, \*SEND or die "$0: copy failed: $!";
close SEND or warn "$0: close: $!"; # later reads hang without this
undef $/;
my $errors = <ERRORS>;
warn $errors if $errors =~ /\S/;
close ERRORS or warn "$0: close: $!";
print <RECV>;
close RECV or warn "$0: close: $!";
Scenario:
I have image files in a directory on the "main" host eg /home/user/public_html/images/red/id100/image01.jpg (thru image012.jpg)
I would like to copy/send them to my remote host creating the red/id100 path if !-d. (the "/images" folder pre exists.)
I need to send a username and password to the remote host as well to get in. It is a typical cpanel shared server environment.
My main server is dedicated, also with cpanel management installed.
I looked into NET::FTP, File::Remote, Net::Telnet and Net::SFTP but, no examples available that were "dumbed" down to my level.
I will eventually need to do this with ascii files too but, I believe once I get it working with the images, I can figure out xfermode switch, I hope.
Thanks for any help and verbose examples. I always learn great things here.
Using SFTP it should be pretty simple:
use Net::SFTP::Foreign;
my $sftp = Net::SFTP::Foreign->new($HOST, passwd => $PASSWD);
$sftp->error and die "Unable to connect to remote host: " . $sftp->error;
$sftp->rput($SRC_BASE, $DST_BASE);
...or using ssh+rsync...
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new($HOST, passwd => $PASSWD);
$ssh->error and die "Unable to connect to remote host: " . $ssh->error;
$ssh->rsync_put({recursive => 1}, $SRC_BASE, $DST_BASE)
or die "rsync failed: " . $ssh->error;

How can I create a TCP server daemon process in Perl?

I wish to create a TCP server daemon process in Perl.
Which is the best framework/module for it?.
Is there anything that comes bundled with Perl?
Edit: Something that has start | stop | restart options would be great.
Edit: It has to be a Multi threaded server.
Well - it's better if you could state what this daemon is supposed to do. As there are specialized frameworks/libraries for various tasks.
For simplest daemon that does nothing, just exists, you can easily do this:
#!/usr/bin/perl
use strict;
use warnings;
use Carp;
use POSIX qw( setsid );
daemonize();
do_your_daemon_stuff();
exit;
sub daemonize {
chdir '/' or croak "Can't chdir to /: $!";
open STDIN, '/dev/null' or croak "Can't read /dev/null: $!";
open STDOUT, '>/dev/null' or croak "Can't write to /dev/null: $!";
defined(my $pid = fork) or croak "Can't fork: $!";
exit if $pid;
setsid or croak "Can't start a new session: $!";
open STDERR, '>&STDOUT' or croak "Can't dup stdout: $!";
}
sub daemonize() was liften from perldoc perlipc (with minor change).
That's all - the code now properly daemonizes, and can do anything you want.
I just read your edit, that you want TCP server.
OK. Here is simplistic code:
#!/usr/bin/perl
use strict;
use warnings;
use Carp;
use POSIX qw( setsid );
use IO::Socket;
my $server_port = get_server_port();
daemonize();
handle_connections( $server_port );
exit;
sub daemonize {
chdir '/' or croak "Can't chdir to /: $!";
open STDIN, '/dev/null' or croak "Can't read /dev/null: $!";
open STDOUT, '>/dev/null' or croak "Can't write to /dev/null: $!";
defined(my $pid = fork) or croak "Can't fork: $!";
exit if $pid;
setsid or croak "Can't start a new session: $!";
open STDERR, '>&STDOUT' or croak "Can't dup stdout: $!";
}
sub get_server_port {
my $server = IO::Socket::INET->new(
'Proto' => 'tcp',
'LocalPort' => 31236,
'Listen' => SOMAXCONN,
'Reuse' => 1,
);
die "can't setup server" unless $server;
return $server;
}
sub handle_connections {
my $port = shift;
my $handled = 0;
while ( my $client = $port->accept() ) {
$handled++;
print $client "Hi, you're client #$handled\n";
chomp ( my $input = <$client> );
my $output = reverse $input;
print $client $output, "\n";
print $client "Bye, bye.\n";
close $client;
}
return;
}
Just remember that this is blocking tcp server, so it will be able to handle 1 connection at the time. If you want more than 1 - it becomes more complex, and you have to ask yourself if you prefer multithreading (or multi-processing), or you prefer single-process, event based server.
You do not actually want to write multithreaded perl. Perl threads are broken - they do not work properly (in my opinion).
Creating a new perl thread clones the entire interpreter including all the data currently in scope - therefore is basically WORSE than creating a new process (which of course, would use copy-on-write) and less useful.
So you definitely don't want it multithreaded.
If possible, I would consider looking at something like AnyEvent as an alternative to a pure threaded approach.
I've never had occasion to try it myself, but I believe POE is highly regarded for that sort of thing.
Here are some examples of TCP servers written with POE.
A quick search reveals quite a few possibilities. Daemon::Generic seems to be straightforward to use.
In addition, there are many server modules for various protocols. In fact, HTTP::Daemon has been a core module for a while now.
"Something that has start | stop | restart options would be great"
There are modules on CPAN which will provide this. E.g., I can see Daemon::Generic which claims to be a framework to provide start/stop/reload for a daemon.
/I3az/