How to send commands to windows command prompt using a PERL script - perl

I want to send some commands to windows command prompt using 'PERL' script.
the command is:
putty.exe -ssh -2 -l username -pw password "ip address"
this command will open an SSH session (console)to the mentioned ip address (server) for me.
after getting the new console, I want to pass commands to and perform operations in the new console.How can I do that as well?
Please help

You can use 'system' or 'exec' command.
system:
#args = ("command", "arg1", "arg2");
system(#args) == 0
or die "system #args failed: $?"
http://perldoc.perl.org/functions/system.html
exec:
exec '/bin/echo', 'Your arguments are: ', #ARGV;
exec "sort $outfile | uniq";
http://perldoc.perl.org/functions/exec.html
Please notice the difference between them.

Related

Perl LFTP Pipe Using SSH Key

I can currently connect to an SFTP server using a username/password combination:
print "Attempting connection...\n";
open( my $LFTP,'|-', "lftp -u $ftpuser,'$ftppwd' -e open -p $ftpport $ftpserver" ) or die "Cannot open lftp: $!";
print $LFTP <<"END";
ls
END
close($LFTP); # die unless lftp exit code is 0
exit 0;
How can change this code to connect to a different server using an SSH key which is encrypted with a passphrase?
This is what I've tried:
print "Attempting connection...\n";
# $ftppwd is blank now!
open( my $LFTP,'|-', "lftp -u $ftpuser,'$ftppwd' -e 'set sftp:connect-program \"ssh -a -x -i $keypath\"; open $ftpserver;'" ) or die "Cannot open lftp: $!";
print $LFTP <<"END";
ls
END
close($LFTP); # die unless lftp exit code is 0
exit 0;
The output is stuck at:
Attempting connection...
`ls' at 0 [Connecting...]
Thank you in advance for any help..
Add -u option to the open command inside -e argument and use the pass phrase as the password. You should also use url syntax to select the sftp protocol, e.g. sftp://user:phrase#server

Undefined subroutine &main::promt

I am sort of new to Perl. I was trying to write a script which will take a mysqldump and restore it in a new database. The main idea is to migrate a DB from one server to another.
Here's the scrip that I wrote:
#!/usr/bin/perl
use warnings;
print "Starting the migration process!\n";
print "Enter the source server address, make sure you enter the FQDN of the server";
$source_address = promt ("Source server address: ");
check_string($source_address);
print "Enter the destination server address, make sure you enter the FQDN of the server";
$destination_address = promt ("Destination server address:");
check_string($destination_address);
print "Enter the Source server password for the root user";
$source_password = promt ("Source server address:");
check_string($source_password);
print "Enter the destination server password for the root user";
$destination_password = promt ("Destination server address:");
check_string($destination_password);
$current_dir = cwd();
system("mysqldump --single-transaction -u root -p$source_password --force -h $source_address -A -R -E --triggers
--routines --max_allowed_packet=512M | gzip -c >$current_dir/old_db_dump.sql") or die "system call to create Mysqldump failed: $?";
system("pt-show-grants -uroot -p$source_password -h $source_address > $current_dir/old_grants.sql") or die "system call to create grant failed: $?";
system("mysql -u root -p$destination_password -h $destination_address < $current_dir/old_db_dump.sql") or die "System call to import the sqldump failed: $?";
system("mysql -u root -p$destination_password -h $destination_address < $current_dir/old_grants.sql") or die "System call to import the grants failed: $?";
# A function that checks if the passed string is null or not
sub check_string{
$string_to_check = $_[0];
if ($string_to_check eq '') {
print "The entered value is empty, the program will exit now, re-run the program";
exit 0;
}
}
sub prompt {
my ($text) = #_;
print $text;
my $answer = <STDIN>;
chomp $answer;
return $answer;
}
But when I try to execute the code, I end up with the following error:
Starting the migration process!
Undefined subroutine &main::promt called at migrate_mysql.pl line 26.
Enter the source server address, make sure you enter the FQDN of the server
For writing the Prompt function, I followed the tutorial mentioned in the post here: http://perlmaven.com/subroutines-and-functions-in-perl
I do not know why am I getting this error here. Do I have to include some packages?
Also it would be nice if you could comment on the system block of the code:
system("mysqldump --single-transaction -u root -p$source_password --force -h $source_address -A -R -E --triggers
--routines --max_allowed_packet=512M | gzip -c >$current_dir/old_db_dump.sql") or die "system call to create Mysqldump failed: $?";
system("pt-show-grants -uroot -p$source_password -h $source_address > $current_dir/old_grants.sql") or die "system call to create grant failed: $?";
system("mysql -u root -p$destination_password -h $destination_address < $current_dir/old_db_dump.sql") or die "System call to import the sqldump failed: $?";
system("mysql -u root -p$destination_password -h $destination_address < $current_dir/old_grants.sql") or die "System call to import the grants failed: $?";
Am I doing it in the right way? Am I passing the variable values in a correct manner?
From this error message:
Undefined subroutine &main::promt called at migrate_mysql.pl line 26.
You should look at line 26. Which is odd, because your error isn't on line 26, but here:
$source_address = promt ("Source server address: ");
If I run your code I get:
Undefined subroutine &main::promt called at line 9.
You've got "promt" not "prompt" which is a subroutine that is undefined.
You should really also add use strict; to your code, and then rejig it - it'll generate a lot more errors initially, but it'll avoid some real gotchas in future if you spell a variable incorrectly.
It's quite easy in your code - just put my in front of the first use of a variable - you've been good with scoping otherwise, but otherwise it means that once you first use $string_to_check it remains visible to the rest of the program, which is just a bit messy and can lead to some odd bugs.

Quoting in bash and perl in recursive ssh command

I am writing a perl script to login in to a server with ssh and do some shell commands on the server. The problem is that the server is only accessible by first logging into another server.
(I am using password-less login with ssh keys).
The following bash script is working correctly, and illustrates the problem:
#! /bin/bash
server1="login.uib.no"
server2="cipr-cluster01"
ssh "$server1" "ssh $server2 \"echo \\\"\\\$HOSTNAME\\\"\""
It prints the correct host name to my screen: cipr-cluster01. However, when trying to do same thing in Perl:
my $server1="login.uib.no";
my $server2="cipr-cluster01";
print qx/ssh "$server1" "ssh $server2 \"echo \\\"\\\$HOSTNAME\\\"\""/;
I get the following output: login.uib.no. So I guess, there is some problems with the quoting for the perl script..
qx works like double quotes. You have to backslash some more:
print qx/ssh "$server1" "ssh $server2 \"echo \\\\"\\\$HOSTNAME\\\\"\""/;
Using single quotes might simplify the command a lot:
print qx/ssh "$server1" 'ssh $server2 "echo \\\$HOSTNAME"'/;
You can simplify the quoting a bit by using the ProxyCommand option that tells ssh to connect to $server2 via $server1, rather than explicitly running ssh on $server1.
print qx/ssh -o ProxyCommand="ssh -W %h:%p $server1" "$server2" 'echo \$HOSTNAME'/;
(There is some residual output from the proxy command (Killed by signal 1) that I'm not sure how to get rid of.)
You can use Net::OpenSSH that is able to do the quoting automatically:
my $ssh_gw = Net::OpenSSH->new($gateway);
my $proxy_command = $ssh_gw->make_remote_command({tunnel => 1}, $host, 22);
my $ssh = Net::OpenSSH->new($host, proxy_command => $proxy_command);
$ssh->system('echo $HOSTNAME');

Password best practice when stdin is in use

I have a script that makes of stdin. It also includes internal calls to curl, that are constructed based on the stdin data, and that require password authentication via form variables in the url.
I'd like to be able to type my password when I run the script, rather than storing it somewhere, but stdin is "taken". What's a good way to write a script like this? I'd be interested in either a good way to keep it in the filesystem or if there's some conceivable way to get it as live input without fouling up the incoming pipe.
Read it from the TTY:
if terminal=$(tty < /dev/tty || tty || tty 0<&1 || tty 0<&2) 2> /dev/null
then
echo "Enter password: " > "$terminal"
IFS= read -r password < "$terminal"
else
echo "There is no terminal to read a password from." >&2
exit 1
fi
This tries to get the terminal associated with /dev/tty, or stdin/stdout/stderr if the OS doesn't support it, and uses it to read and write directly to the user.
If it doesn't have to be portable, e.g. when using use Bash on Linux or FreeBSD, you can simplify and improve this:
if ! IFS= read -rs -p "Enter password: " password < /dev/tty 2> /dev/tty
then
echo "Password entry failed"
exit 1
fi
At risk of muddying the question, I needed to switch over to perl and thought it might be useful to some people who find themselves here if I posted a perl translation of "that other guy"'s answer. (Don't know if this is the cleanest way, but it worked for me.)
open (TTY, "+< /dev/tty" )
or eval 'sub Term::ReadLine::findConsole { ("&STDIN", "&STDERR") }';
die $# if $#;
print TTY "Enter your password: ";
use Term::ReadKey;
ReadMode('noecho', *TTY);
my $password = ReadLine(0, *TTY);
chomp $password;
ReadMode('normal', *TTY);
print TTY "\n";
close (TTY);

How to capture error message from prompt - shell or perl

I am trying to capture the output of a command. It works fine if the command executes. However when there is an error, i am unable to capture what gets displayed in commandline
Eg.
$ out=`/opt/torque/bin/qsub submitscript`
qsub: Unauthorized Request MSG=group ACL is not satisfied: user abc#xyz.org, queue home
$ echo $out
$
I want $out to have the message
Thanks!
Errors are on stderr, so you need to redirect them into stdout so the backticks will capture it:
out=`/opt/torque/bin/qsub submitscript 2>&1`
if [ $? -gt 0 ] ; then
# By convention, this is sent to stderr, but if you need it on
# stdout, just remove the >&2 redirection
echo "Error: $out" >&2
else
echo "Success: $out"
fi
You should test the exit status of the command to figure out what the output represents (one way shown). It is similar for perl, slightly different syntax of course.
Have you tried doing it like this
$ out=`/opt/torque/bin/qsub submitscript 2>&1 > /dev/null`
$ echo $out