I am trying to run a couple of commands in putty from perl. Right now my code gets me into putty but I am unsure of how to execute commands from there.
my $PUTTY = 'C:\Users\Desktop\putty.exe';
my $dacPutty = "$PUTTY, -ssh username#server - l username -pw password";
system ($dacPutty);
system (ls);
use plink instead. ( http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter7.html )
plink is in the same directory as putty.
Usually in Perl it's better to use a Perl module, where one exists, than to shell out.
Using a module is more portable, and often gives you more control. system introduces many opportunities for security bugs, so it's good to avoid it where possible.
In this case, use Net::SSH::Perl http://search.cpan.org/~turnstep/Net-SSH-Perl-1.38/lib/Net/SSH/Perl.pm
Once installed:
use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new("host1");
$ssh->login("user1", "pass1");
$ssh->cmd("cd /some/dir");
$ssh->cmd("foo");
For reliability, you should actually check the result of each cmd:
my ($stdout, $stderr, $exit) = $ssh->cmd("cd /some/dir");
unless ($exit == 0) {
// Handle failed cd
}
The document notes that with SSH-1, each cmd reconnects, so the above would not work -- you would cd in one shell, then foo in a completely new shell. If you have to use SSH-1, then you'd need to do:
$ssh->cmd("cd /some/dir; foo");
(And you can use a similar trick even if you're making a system call to plink)
Related
I have a situation where in I am calling the below Perl script
if (param("lremail") && param("lot")) {
my $address=param("lremailaddress");
my $lot=param("lot");
print a({-href=>"$dir/new.pl"},"Back to Top"),br;
print "Request submitted for $address.",br;
print "Lot $lot",br;
print "You will receive an e-mail with a link to the data when the request is complete.";
print end_html;
system ("ssh SERVERNAME /test/abc.csh $lot $$ $address &");
exit(1);
The above script does not run because when I execute the system is prompted for a password. Then I looked it up and found the below command..
expect -c 'spawn ssh SERVERNAME /test/abc.csh J213520 06 abc#gmail.com "ls -lh file"; expect "Password:"; send "PASSWORD\r"; interact'
The above command is executed successfully without any issue but from the command line only. When I incorporate the same(by replacing the system call) within the Perl script, it fails. How can I incorporate within the first script?
Reiterating and adding to comments:
Consider using a key-based authentication either with passphrase-less keys or with ssh-agent (e.g., using ssh-keygen generated/managed identities);
Consider using sshpass or another expect-like external;
Consider using the Perl Expect or an equivalent CPAN module; and/or,
Consider using the Perl Net::SSH or an equivalent CPAN module.
Also, system can easily introduce remote code execution vulnerabilities, especially when using its system LIST syntax.
I have a program with lots of system commands to handle searching for, examining, and killing processes:
system qq(kill $pid);
and
for my $pid ( qx( pgrep -f "$pgrep_re") ) {
chomp $pid;
...
}
and
my $command_line = qx(ps -o command="" $pid);
chomp $command_line;
....
Not only is this system specific, but I'm depending upon the user to have these particular commands in their path the correct way, leaving me with a system security issue (like some joker setting alias ps="rm -rf *").
I would like to do this stuff in a nice, Perl way which would be less dependent upon all of these system commands and be a bit more platform independent1.
Is there a Perl module? Bonus points for one that does it in a nice object-oriented way and doesn't depend externally with these very same commands.
1. A lot of this deals with using ssh and setting up tunnels, so since Windows doesn't have ssh as a native command, I'm willing to exclude it as long as this works well for other Unix/Linux systems.
kill: use the builtin kill (perldoc -f kill)
ps: use search.cpan.org, there is UNIX::Process. In linux you could also scan through /proc/
pgrep: combine ps with perl pattern matching
I am bit stuck here I want to ssh in to a machine and then run about 3 commands which are basically setup commands and then i want to return back to my machine with env variables of that machine
like
setup1
setup2
setup3
env > envtext.txt.
return back
All this i have to do in perl
i tried commands like
system("ssh #machine command1 && command 2") doesnt work
is there something like?
system("ssh #machine command1 -cmd command 2 -cmd command 3")
if not than what is the best way to do it
like making a shell script then calling it or i can do it in perl itself without any shell scripts?
code
#!/usr/bin/perl -w
use Net::SSH::Perl;
my $host = "address";
my $user = "name";
my $password = "password";
-- set up a new connection
my $ssh = Net::SSH::Perl->new($host,
debug=>0,
identity_files => ['path to key'],
options=> ["StrictHostKeyChecking no"]
#interactive => yes,
);
-- authenticate
$ssh->login($user,$password);
-- execute the command
my($stdout, $stderr, $exit) = $ssh->cmd("env");
print $stdout;`
error it gives is Permission denied at ssh.pl line 25
Thank you
I think your question is about SSHing to a single remote host and running multiple commands there. If that's true, then you need to pack your multiple commands up into a single command line that the remote shell can execute. The easiest way to do this is to use the list form of system, and pass the command line as a single parameter:
system "ssh", "machine", "setup1; setup2; setup3";
On to the second part of your question: You want to get data back from the remote side. For that, you'll want your program to read SSH's output rather than using system. For this, you can use:
open my $FH, "-|", "ssh", "machine", "setup1; setup2; setup3; env";
my #lines_from_ssh = <$FH>;
close $FH;
If you also need to send input to the remote side, look into IPC::Open2. If you need to capture both stdout and stderr, see IPC::Open3.
What you can do :
system("ssh $_ command1 -cmd command 2 -cmd command 3") for #machines;
Another Pure Perl solution is to use Net::OpenSSH
I am very new to perl. I am trying to create a perl script which will execute multiple unix command to create VNC session in some unix server.
Here is my script -
#!/usr/bin/perl -w
use Carp;
use strict;
use warnings;
# here get the parameters idsid
my $IdsId=$ARGV[0];
#excecute the commands here
my $user=`su -l $IdsId`;
my #finalresult=`vncserver -randr 1024x768,800x600,1024x768,1152x824,1280x1024,1280x800,1440x900,1400x1050,1600x1200,1920x1200`;
print "#finalresult";
But when I am executing this script its not working.
Please some body help me.
I would expect to see you executing:
exec "su", "-l", "$IdsID", "-c", "vncserver -randr ...";
which makes the Perl script largely irrelevant since you could write it in shell as:
exec su -l "${1:-$USER}" -c "vncserver -randr ..."
It might be better to use sudo rather than su. The difference is that with su, you have to know the other user's password; with sudo, you only have to know your own password (and the system administrator must have given you permission to use sudo for the task on hand).
When you use backticks, a sub shell is created and the main program is halted. When the process in that sub shell is finished, the control returns to the main program. So in this case, I imagine that su never exits, and that vncserver does not run with the user you intend (nor does it exit to return control to the perl script) -- because it is executed in another sub shell where su never happened.
What you probably need is to do these commands in the same line:
my #result = qx(su -l $IdsId; vncserver -randr ....);
Although whether this works or not you'll have to find out for yourself.
I am new to this module. I tried a sample program and it worked fine. But, now I would like to how do I execute multiple commands in this program :
use Net::SSH::Perl;
my $hostname = "<<hostname>>";
my $username = "<<username>>";
my $password = "<<password>>";
my $cmd = 'mkdir script; cd script';
my $ssh = Net::SSH::Perl->new("$hostname", debug=>0);
$ssh->login("$username","$password");
my ($stdout,$stderr,$exit) = $ssh->cmd("$cmd");
print $stdout;
You can just call cmd repeatly.
The problem you are facing may be that every command is run in a different shell and commands that are run for their side effects as cd or export become useless.
As a work around you can prefix all the commands with the cd $dir command. For instance:
my ($stdout1, $stderr1, $exit1) = $ssh->cmd("cd /$dir && $cmd1");
my ($stdout2, $stderr2, $exit2) = $ssh->cmd("cd /$dir && $cmd2");
...
Another option is to run a shell on the remote host and talk to it, but this is more difficult and error prone.
Finally, Net::SSH::Perl is old and unmaintained, nowadays, Net::SSH2 or Net::OpenSSH are usually better options.