File Coverage

lib/Rex/Helper/SSH2.pm
Criterion Covered Total %
statement 17 88 19.3
branch 0 28 0.0
condition 0 4 0.0
subroutine 6 8 75.0
pod 0 2 0.0
total 23 130 17.6


line stmt bran cond sub pod time code
1             #
2             # (c) Jan Gehring
3             #
4              
5             package Rex::Helper::SSH2;
6              
7 83     83   1131 use v5.12.5;
  83         324  
8 83     83   437 use warnings;
  83         201  
  83         3857  
9              
10             our $VERSION = '1.14.3'; # VERSION
11              
12             require Exporter;
13 83     83   515 use Data::Dumper;
  83         173  
  83         4864  
14             require Rex::Commands;
15 83     83   2048 use Time::HiRes qw(sleep);
  83         16324  
  83         526  
16              
17 83     83   11531 use base qw(Exporter);
  83         199  
  83         7116  
18              
19 83     83   546 use vars qw(@EXPORT);
  83         283  
  83         67142  
20             @EXPORT = qw(net_ssh2_exec net_ssh2_exec_output net_ssh2_shell_exec);
21              
22             our $READ_STDERR = 1;
23             our $EXEC_AND_SLEEP = 0;
24              
25             sub net_ssh2_exec {
26 0     0 0   my ( $ssh, $cmd, $base, $option ) = @_;
27              
28 0           my $chan = $ssh->channel;
29              
30             # REQUIRE_TTY can be turned off by feature no_tty
31 0 0         if ( !Rex::Config->get_no_tty ) {
32 0           $chan->pty("xterm"); # set to xterm, due to problems with vt100.
33             # if vt100 sometimes the restart of services doesn't work and need a sleep .000001 after the command...
34             # strange bug...
35 0           $chan->pty_size( 4000, 80 );
36             }
37 0           $chan->blocking(1);
38              
39 0           $chan->exec($cmd);
40              
41 0           my $in;
42 0           my $in_err = "";
43              
44 0   0       my $rex_int_conf = Rex::Commands::get("rex_internals") || {};
45 0           my $buffer_size = 1024;
46 0 0         if ( exists $rex_int_conf->{read_buffer_size} ) {
47 0           $buffer_size = $rex_int_conf->{read_buffer_size};
48             }
49              
50 0           my @lines;
51             my $last_line;
52 0           my $current_line = "";
53 0           while ( my $len = $chan->read( my $buf, $buffer_size ) ) {
54 0           $in .= $buf;
55 0           $current_line .= $buf;
56              
57 0 0         if ( $buf =~ m/\n/ms ) {
58 0           @lines = split( /\n/, $current_line );
59 0 0         unshift @lines, $last_line if ($last_line);
60 0           $last_line = pop @lines;
61              
62 0           for my $line (@lines) {
63 0           $line =~ s/[\r\n]//gms;
64 0           $line .= "\n";
65 0 0         $base->execute_line_based_operation( $line, $option ) && goto END_READ;
66             }
67              
68 0           $current_line = "";
69             }
70              
71             }
72              
73 0           my @lines_err;
74 0           my $last_line_err = "";
75 0           while ( my $len = $chan->read( my $buf_err, $buffer_size, 1 ) ) {
76 0           $in_err .= $buf_err;
77 0           @lines_err = split( /\n/, $buf_err );
78 0 0         unshift @lines_err, $last_line_err if ($last_line_err);
79 0           $last_line_err = pop @lines_err;
80              
81 0           for my $line (@lines_err) {
82 0           $line =~ s/[\r\n]//gms;
83 0           $line .= "\n";
84 0 0         $base->execute_line_based_operation( $line, $option ) && goto END_READ;
85             }
86             }
87              
88             #select undef, undef, undef, 0.002; # wait a little before closing the channel
89             #sleep 1;
90             END_READ:
91 0           $chan->send_eof;
92              
93 0           my $wait_c = 0;
94 0   0       my $wait_max = $rex_int_conf->{ssh2_channel_closewait_max} || 500;
95 0           while ( !$chan->eof ) {
96 0           Rex::Logger::debug("Waiting for eof on ssh channel.");
97 0           sleep 0.002; # wait a little for retry
98 0           $wait_c++;
99 0 0         if ( $wait_c >= $wait_max ) {
100              
101             # channel will be force closed.
102 0           Rex::Logger::debug(
103             "Rex::Helper::SSH2::net_ssh2_exec: force closing channel for command: $cmd"
104             );
105 0           last;
106             }
107             }
108              
109 0           $chan->wait_closed;
110 0           $? = $chan->exit_status;
111              
112             # if used with $chan->pty() we have to remove \r
113 0 0         if ( !Rex::Config->get_no_tty ) {
114 0 0         $in =~ s/\r//g if $in;
115 0 0         $in_err =~ s/\r//g if $in_err;
116             }
117              
118 0 0         if (wantarray) {
119 0           return ( $in, $in_err );
120             }
121              
122 0           return $in;
123             }
124              
125             sub net_ssh2_exec_output {
126 0     0 0   my ( $ssh, $cmd, $callback ) = @_;
127              
128 0           my $chan = $ssh->channel;
129 0           $chan->blocking(1);
130              
131 0           $chan->exec($cmd);
132              
133 0           while (1) {
134 0           my $buf;
135             my $buf_err;
136 0           $chan->read( $buf, 15 );
137 0           $chan->read( $buf_err, 15 );
138              
139 0 0         if ($callback) {
140 0           &$callback( $buf, $buf_err );
141             }
142             else {
143 0           print $buf;
144 0           print $buf_err;
145             }
146              
147 0 0         last unless $buf;
148             }
149              
150 0           $chan->close;
151 0           $? = $chan->exit_status;
152              
153             }
154              
155             1;