Open glasswalk3r opened 8 years ago
Hi,
I was able to implemented that using Moo with partial success: the log feature of plink doesn't block the program to print to STDOUT. Here is a example witha workaround
sub exec {...}
You can use Net::SSH::Any in a pretty similar fashion:
$ssh->system({ stdout_fh => $log_fh, stderr_to_stdout => 1}, $cmd);
Though, underneath, things are done in an equivalent but different way, so it may still trigger the same bug you were seeing before.
The thing is that I would not like to add a workaround for a bug that has not been properly identified because any code change could reintroduce it again.
Could you create a bug report with some further information about the issue and a minimal program able to reproduce it?
Hi,
I was able to implemented that using Moo with partial success: the log feature of plink doesn't block the program to print to STDOUT. Here is a example witha workaround sub exec {...}
You can use Net::SSH::Any in a pretty similar fashion:
$ssh->system({ stdout_fh => $log_fh, stderr_to_stdout => 1}, $cmd);
Though, underneath, things are done in an equivalent but different way, so it may still trigger the same bug you were seeing before.
The thing is that I would not like to add a workaround for a bug that has not been properly identified because any code change could reintroduce it again.
Could you create a bug report with some further information about the issue and a minimal program able to reproduce it?
Understood you point and it's very reasonable.
I'm not sure how provide evidences in those cases... the threads just stuck, I get no output at all.
The "main" thread uses a "tee like" feature (prints messages to STDOUT and to a log file), but when those errors arise, I stop seeing messages on STDOUT (and sometimes in the log files either).
At the end, I need to manually kill the plink and perl processes.
Maybe it could be possible to turn on the -sshlog
option of plink? Let me know if you're willing to have a patch with that.
Hi,
I think that if I share some code with you would be easier for you to try to see the errors yourself.
Of course you will need to use Windows (I'm with Windows 7, Strawberry Perl 5.24.0) and you will not have the program that is actually executing on the servers, but I think you can replace that quite easily (take a look at ssh_2_server
sub).
sub ssh_2_server {
my $opts_ref = shift;
my $log = File::Spec->catfile( getcwd(), 'logs', ( $opts_ref->{server} . '.log' ) );
my $is_log_ok = open( my $out, '>>', $log );
my $cmd;
if ( exists($opts_ref->{os_only}) and $opts_ref->{os_only} ) {
$cmd = 'cview.pl -i ' . $opts_ref->{instance} . ' -o';
} elsif ( exists($opts_ref->{clean_cache}) and $opts_ref->{clean_cache} ) {
$cmd = 'cview.pl -i ' . $opts_ref->{instance} . ' -s ' . $opts_ref->{sr_num} . ' -e 0';
} else {
$cmd = 'cview.pl -i ' . $opts_ref->{instance} . ' -s ' . $opts_ref->{sr_num};
}
if ($is_log_ok) {
my $start = DateTime->now();
my $errors = 0;
print $out join(' ', 'Connecting to', $opts_ref->{server}, 'under', $opts_ref->{instance},'...');
my $ssh;
my $fqdn = $opts_ref->{server} . '.oracleoutsourcing.com';
try {
$ssh = Net::SSH::Any->new($fqdn, user => $user, password => $password, backend => 'Plink_Cmd', local_plink_cmd => 'C:\\Program Files (x86)\\PuTTY\\plink.exe');
} catch {
$errors++;
warn $_;
return ssh_exception( $out, $_, $errors, $start, $opts_ref->{server}, $opts_ref->{instance});
};
unless ( defined(blessed($ssh)) ) {
$errors++;
return ssh_exception( $out, 'Could not create an instance of Net::SSH::Any', $errors, $start, $opts_ref->{server}, $opts_ref->{instance});
} else {
print $out "done\n";
print $out "Executing commands '$cmd'...\n";
my ($stdout, $stderr) = $ssh->capture2(". .bash_profile; $cmd");
if ( $ssh->error ) {
$errors++;
warn "STDERR:\n[$stderr]\n";
warn $ssh->error;
return ssh_exception( $out, $ssh->error, $errors, $start, $opts_ref->{server}, $opts_ref->{instance});
}
print $out "STDOUT:\n[$stdout]\n";
print $out "STDERR:\n[$stderr]\n";
print $out "Done executing commands\n";
print $out 'Trying to copy response file... ';
try {
my $sftp = $ssh->sftp;
unless ( defined(blessed($sftp)) ) {
confess $ssh->error;
}
get_response( $sftp, $opts_ref->{server}, $opts_ref->{instance} );
} catch {
print $out $_;
$errors++;
};
print $out "Done copying files\n";
}
my $elapsed = calc_elapsed( $start );
print $out join(' ', 'Operation took', $elapsed, "seconds to finish\n");
close($out);
return ( $errors, $elapsed, $opts_ref->{server}, $opts_ref->{instance} );
}
else {
warn "Failed to create log: $!";
return ( 1, 0, $opts_ref->{server}, $opts_ref->{instance} );
}
}
The program will create threads (limited by parameter) and then collect results from the remote program (a XML file) by using SFTP. The target would be different Linux hosts, and last time I executed I had about 90 servers to loop over.
I don't see any particular behavior when errors occurred, and not with a specific host: the plink connection just "hangs" and I have to kill it manually. No error message is generated. I updated the full code, just let me know if you need some pointers with it.
Hi!
I've being use your distro successfully until I moved my code to use Perl ithreads: after that, some connections just fail... and I don't get any error message or something like that. I'm connecting to multiple SSH server from Windows. Considering that ithreads is somehow messy and Net::SSH and IPC messy on Windows, I decided to take a shot and try to run plink by using the batch mode and logging messages directly to a file. I forked your project and tried to implemented "true batch mode" with Putty plink, but it seems I would broke the current interface, so not sure if you would be interested in implementing this (and how). I was able to implemented that using Moo with partial success: the log feature of plink doesn't block the program to print to STDOUT. Here is a example witha workaround
Not elegant, but it works. The messy part is using
system()
and allowing the shell interpreter taking action. Not very safe, but at least I'm not getting external data (I think, I should turn taint mode on to validate that).Error detection is a bit primitive too... the code is not reading the log file and searching for error messages.
Best news is that I'm able to connect to multiple SSH server with ithreads on Windows... if you want to implement such a thing, I'm willing to give a hand.