I am trying to use below perl code to ssh into linux machine and pull output of ls -l but it doesnt seem to be working.
What am i doing wrong?
#!/usr/bin/perl
use warnings;
use strict;
use Net::Telnet;
use IO::Pty;
use POSIX 'setsid';
use Getopt::Long;
use constant PROMPT => '/[a-z#>]/';
my $host = "192.168.1.121";
my $user = "root";
my $ssh = do_cmd( 'ssh', "-l$user", $host );
my $shell = Net::Telnet->new( Fhopen => $ssh );
$shell->binmode(1);
$shell->cmd( String => 'test', Prompt => '/[a-z]/' );
$shell->waitfor(PROMPT);
my #lines = $shell->cmd( String => 'ls -l', Prompt => '/[a-z]/' );
print #lines;
print "\n";
sub do_cmd {
my ( $cmd, #args ) = #_;
my $pty = IO::Pty->new;
defined( my $child = fork );
return $pty if $child;
setsid();
my $tty = $pty->slave;
close $pty;
STDIN->fdopen( $tty, "<" );
STDOUT->fdopen( $tty, ">" );
STDERR->fdopen( $tty, ">" );
close $tty;
$| = 1;
exec $cmd, #args;
}
Telnet and SSH are two different programs. You can't use telnet client for ssh server.
Related
I am creating a perl script in which I have to ssh multiple servers from same script and perform same commands on all these remote servers.
Right now I am using "If loop" and call all other servers from this script and perform command on them.
I want to create a function with these set of commands, that I need to perform on these different servers.
if($random_number==1){
use Net::SSH::perl
use lib qw("user/share/perl5/");
my $hostname = "10.*.*.*";
my $username = "root";
my $password = "root\#123";
my $cmd1 = "ls /home/ashish/"
my $cmd2 = "netstat -na | grep *.*.*.*;
$ssh->login("$username" , "$password");
my ($stdout,$stderr,$exit) = $ssh->cmd("$smd1" && "$cmd2");
print $stdout;
}
the above commands after if syntax needs to be repeated for different servers.
want to use a function call.
Start with general programming toutorials, then do it like:
use Net::SSH::perl;
use strict;
use warnings;
my #servers = (
{
hostname => 'somehost1',
username => 'someuser1',
password => 'somepass1',
commands => ['somecmd11','somecmd12'],
},
{
hostname => 'somehost2',
username => 'someuser2',
password => 'somepass2',
commands => ['somecmd21','somecmd22'],
},
# ...
);
do_something_on_remote_servers_one_by_one( #servers );
exit(0);
sub do_something_on_remote_servers_one_by_one {
my (#servers) = #_;
foreach my $server (#servers) {
my $ssh = Net::SSH::perl->new($server->{hostname});
$ssh->login($server->{username}, $server->{password});
my $cmd_string = join(' & ', #{ $server->{commands} } );
my ($stdout,$stderr,$exit) = $ssh->cmd($cmd_string);
print $stdout;
}
}
After that, you can think about executing commands in paralell.
I have a Perl script that creates a daemon listening from a socket. When I execute the client to send data to the socket gets connected without problems. But the daemon should be queried from other users and it is not possible.
This is the daemon Perl script (assume that readFile() returns a predefined string):
#!/usr/bin/perl
use POSIX qw(setsid);
use strict;
use warnings;
use IO::Socket;
use Term::ANSIColor;
&daemonize;
my $port = '7070';
my $sock = new IO::Socket::INET(
LocalHost => '127.0.0.1',
LocalPort => '7070',
Proto => 'tcp',
Listen => 1,
Reuse => 1,
);
die `date` . "Could not create socket: $!\n" unless $sock;
while (1) {
my $new_sock = $sock->accept();
my $data = "";
$new_sock->recv( $data, 1024 );
print $data;
my $result = &readFile($data);
$new_sock->send($result);
shutdown( $new_sock, 1 );
}
close($sock);
sub daemonize {
chdir '/' or die "Can't chdir to /: $!";
umask 0;
open STDIN, '/dev/null' or die `date` . "Can't read /dev/null: $!";
open STDOUT, '>/home/bsc99/bsc99871/ACCO/pid' or die `date` . "Can't write to SDTOUT: $!";
open STDERR, '>>', '/home/bsc99/bsc99871/ACCO/ACCOUNT_ERROR.log' or die `date` . "Can't write to STDERR: $!";
defined( my $pid = fork ) or die `date` . "Can't fork: $!";
exit if $pid;
print $$;
setsid or die "Can't start a new session: $!";
}
This is the client:
my $sock = new IO::Socket::INET(
PeerAddr => '127.0.0.1',
PeerPort => '7070',
Proto => 'tcp',
Timeout => 3,
) or die "Could not create socket: $!\n";
# data to send to a server
my $req = $ARGV[0];
my $size = $sock->send($req);
# notify server that request has been sent
shutdown( $sock, 1 );
# receive a response of up to 1024 characters from server
my $response = "";
$sock->recv( $response, 1024 );
print $response;
$sock->close();
if I login as other user different than the one who start the daemon. I can run netstat command and see:
user#login4:> netstat -putan or lsof | grep 7070
(No info could be read for "-p": geteuid()=1801 but you should be root.)
I understand the message but my doubt is if there is any solution like a creating a public socket other than running the daemon as root, because I haven't root access.
How to avoid the hard coded username/password in perl script
I am new to perl I have tried lot of things nothing worked out for me, Please help to provide some method to read the username/password from config file. What things I need to change here,
Below is my perl script:
#!/usr/bin/perl -w
use strict;
use warnings;
use Net::SFTP::Foreign;
my $server="sftp.abcpvt.com";
my $remote="outgoing_folder";
my $user="auser";
my $LOCAL_PATH="/home/sara";
my $file_transfer="DATA.ZIP";
my $password="abc123"
my %args = (user => "$user", password => "$password");
chdir $LOCAL_PATH or die "cannot cd to ($!)\n";
my $sftp = Net::SFTP::Foreign->new(host=>$server,user=>$user,password=>$password) or die "unable to connect";
$sftp->error and die "SSH connection failed: " . $sftp->error;
$sftp->get("$remote/$file_transfer","$LOCAL_PATH/$file_transfer") or die "unable to retrieve file".$sftp->error;
undef $sftp;
exit;
MY config file contains below thing.
Username = “auser”;
Password = “abc123”;
Time_out=180;
Port = 22
I tried the below things,
my $user=get_credentials("/home/sar/config");
my $password=get_credentials("/home/sar/config");
sub get_credentials {
my ($file) = #_;
open my $fh, "<", $file or die $!;
my $line = <$fh>;
chomp($line);
my ($user, $pass) = split /:/, $line;
return ($user, password => $pass);
}
Here I am getting only the password, Username is not getting here…
Could you please share the sample coding for using the username/password in perl script.
I think you want something like this.
sub get_config {
my ($file) = #_;
open my $fh, "<", $file or die $!;
my %config;
while (<>) {
chomp;
next unless /\S/;
my ($key, $val) = split /\s*=\s*/;
$val =~ s/^"//;
$val =~ s/"$//;
%config{$key} = $val;
}
return \%config;
}
my $config = get_config('/home/a911091/config');
my $user = $config->{Username};
my $pass = $config->{Password};
But you'd be far better off looking for a config file module from CPAN.
I have a Linux (openSUSE 10.X) box and have a SFTP service on it.
When someone puts a file I have to write a script to move the files to another dir. I do not want to write a cron job. Is there an event or something I can check to see if they have sent the file?
You can write a c application and hook into inotify events.
Check also Net::SFTP::Server, an SFTP server written in Perl that can be extended to do things like the one you need.
Some code:
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename ();
my $server = Server->new(timeout => 15);
$server->run;
exit(0);
package Server;
use Net::SFTP::Server::Constants qw(SSH_FXF_WRITE);
use parent 'Net::SFTP::Server::FS';
sub handle_command_open_v3 {
my ($self, $id, $path, $flags, $attrs) = #_;
my $writable = $flags & SSH_FXF_WRITE;
my $pflags = $self->sftp_open_flags_to_sysopen($flags);
my $perms = $attrs->{mode};
my $old_umask;
if (defined $perms) {
$old_umask = umask $perms;
}
else {
$perms = 0666;
}
my $fh;
unless (sysopen $fh, $path, $pflags, $perms) {
$self->push_status_errno_response($id);
umask $old_umask if defined $old_umask;
return;
}
umask $old_umask if defined $old_umask;
if ($writable) {
Net::SFTP::Server::FS::_set_attrs($path, $attrs)
or $self->send_status_errno_response($id);
}
my $hid = $self->save_file_handler($fh, $flags, $perms, $path);
$self->push_handle_response($id, $hid);
}
sub handle_command_close_v3 {
my $self = shift;
my ($id, $hid) = #_;
my ($type, $fh, $flags, $perms, $path) = $self->get_handler($hid);
$self->SUPER::handle_command_close_v3(#_);
if ($type eq 'file' and $flags & SSH_FXF_WRITE) {
my $name = File::Basename::basename($path);
rename $path, "/tmp/$name";
}
}
Save the script to somewhere in your server, chmod 755 $it, and configure OpenSSH to use it as the SFTP server instead of the default one.
I have wrote this Perl script to automate my wireless connections:
#!/usr/bin/perl
use strict;
my #modes = ("start", "stop");
my $mode = $modes[0];
my $kill_command = "sudo kill -TERM ";
sub check_args
{
if($#ARGV != 0)
{
print(STDERR "Wrong arguments\n");
print(STDERR "Usage: ./wicd.pl start|stop\n");
exit();
}
my #aux = grep(/^$ARGV[0]$/, #modes);
if (!#aux)
{
print(STDERR "Unknown argument\n");
print(STDERR "Usage: ./wicd.pl start|stop\n");
exit();
}
$mode = $ARGV[0];
}
check_args();
my #is_wicd_running = `ps -A | grep wicd`;
# START
if ($mode eq $modes[0])
{
if (!#is_wicd_running)
{
system("gksudo ifconfig wlan0 down");
system("sudo macchanger -r wlan0");
system("sudo wicd");
}
my #is_wicd_gui_running = grep(/wicd-client/, #is_wicd_running);
if (!#is_wicd_gui_running)
{
system("gksudo wicd-gtk &");
}
}
# STOP
else
{
for (#is_wicd_running)
{
my #aux = split(/ /, $_);
system("$kill_command$aux[1]");
}
system("sudo ifconfig wlan0 down");
}
The problem is that macchanger and sudo ifconfig wlan0 down are not executing (only those...). The weird thing is that those call do execute when calling the script through Perl debugger (perl -d). I thought this could be a timing problem and added some sleep() calls before those calls, but no change. I also tried with system() calls with no change as well.
EDIT: more strange, I've found that if I run the script as perl wicd.pl it runs properly, while ./wicd.pl does not (it runs but has the problem described above). I've attached the whole script. The Perl interpreter used on the header is the same that which perl command returns.
Any clues? Thanks in advance!
More information may help, along with assuring that a \n always ends the output line. Try your running commands within
sub runx
{
foreach my $cmd ( #_ )
{
my $out = qx("$cmd 2>&1");
my $x = $?;
$out =~ s/\s*$/\n/s;
printf "\%s (0x\%0x):\n\%s", $cmd, $x, $out;
last if $x;
}
return $x;
}
No time to run this code this morning and can't delete my prior comment. But somethings running a "which" command can also assure your command is on PATH.