1# 2# (c) Jan Gehring <jan.gehring@gmail.com> 3# 4# vim: set ts=2 sw=2 tw=0: 5# vim: set expandtab: 6 7package Rex::Helper::Run; 8 9use 5.010001; 10use strict; 11use warnings; 12 13our $VERSION = '1.13.4'; # VERSION 14 15require Exporter; 16use base qw(Exporter); 17use vars qw(@EXPORT); 18 19use Net::OpenSSH::ShellQuoter; 20use Rex::Interface::File; 21use Rex::Interface::Fs; 22use Rex::Helper::Path; 23use Carp; 24require Rex::Commands; 25require Rex::Config; 26 27@EXPORT = qw(upload_and_run i_run i_exec i_exec_nohup); 28 29sub upload_and_run { 30 my ( $template, %option ) = @_; 31 32 my $rnd_file = get_tmp_file; 33 34 my $fh = Rex::Interface::File->create; 35 $fh->open( ">", $rnd_file ); 36 $fh->write($template); 37 $fh->close; 38 39 my $fs = Rex::Interface::Fs->create; 40 $fs->chmod( 755, $rnd_file ); 41 42 my @argv; 43 my $command = $rnd_file; 44 45 if ( exists $option{with} ) { 46 $command = Rex::Config->get_executor_for( $option{with} ) . " $command"; 47 } 48 49 if ( exists $option{args} ) { 50 $command .= join( " ", @{ $option{args} } ); 51 } 52 53 return i_run("$command 2>&1"); 54} 55 56# internal run command, doesn't get reported 57sub i_run { 58 my $cmd = shift; 59 my ( $code, $option ); 60 $option = {}; 61 if ( ref $_[0] eq "CODE" ) { 62 $code = shift; 63 } 64 if ( scalar @_ > 0 ) { 65 $option = {@_}; 66 } 67 68 $option->{valid_retval} ||= [0]; 69 $option->{fail_ok} //= 0; 70 71 if ( $option->{no_stderr} ) { 72 $cmd = "$cmd 2>/dev/null"; 73 } 74 75 if ( $option->{stderr_to_stdout} ) { 76 $cmd = "$cmd 2>&1"; 77 } 78 79 if ( ref $option->{valid_retval} ne "ARRAY" ) { 80 $option->{valid_retval} = [ $option->{valid_retval} ]; 81 } 82 83 my $is_no_hup = 0; 84 my $tmp_output_file = get_tmp_file(); 85 if ( exists $option->{nohup} && $option->{nohup} ) { 86 $cmd = "nohup $cmd >$tmp_output_file"; 87 delete $option->{nohup}; 88 $is_no_hup = 1; 89 } 90 91 my $path; 92 93 if ( !Rex::Config->get_no_path_cleanup() ) { 94 $path = join( ":", Rex::Config->get_path() ); 95 } 96 97 my $exec = Rex::Interface::Exec->create; 98 my ( $out, $err ) = $exec->exec( $cmd, $path, $option ); 99 my $ret_val = $?; 100 101 chomp $out if $out; 102 chomp $err if $err; 103 104 $Rex::Commands::Run::LAST_OUTPUT = [ $out, $err ]; 105 106 $out ||= ""; 107 $err ||= ""; 108 109 if ( scalar( grep { $_ == $ret_val } @{ $option->{valid_retval} } ) == 0 ) { 110 if ( !$option->{fail_ok} ) { 111 Rex::Logger::debug("Error executing `$cmd`: "); 112 Rex::Logger::debug("STDOUT:"); 113 Rex::Logger::debug($out); 114 Rex::Logger::debug("STDERR:"); 115 Rex::Logger::debug($err); 116 117 if ($is_no_hup) { 118 $out = $exec->exec("cat $tmp_output_file ; rm -f $tmp_output_file"); 119 $Rex::Commands::Run::LAST_OUTPUT = [$out]; 120 $? = $ret_val; 121 } 122 123 confess("Error during `i_run`"); 124 } 125 } 126 127 if ($code) { 128 return &$code( $out, $err ); 129 } 130 131 if (wantarray) { 132 return split( /\r?\n/, $out ); 133 } 134 135 if ($is_no_hup) { 136 $out = $exec->exec("cat $tmp_output_file ; rm -f $tmp_output_file"); 137 $Rex::Commands::Run::LAST_OUTPUT = [$out]; 138 $? = $ret_val; 139 } 140 141 return $out; 142} 143 144sub i_exec { 145 my ( $cmd, @args ) = @_; 146 147 my $exec = Rex::Interface::Exec->create; 148 my $quoter = Net::OpenSSH::ShellQuoter->quoter( $exec->shell->name ); 149 150 my $_cmd_str = "$cmd " . join( " ", map { $quoter->quote($_) } @args ); 151 152 i_run $_cmd_str; 153} 154 155sub i_exec_nohup { 156 my ( $cmd, @args ) = @_; 157 158 my $exec = Rex::Interface::Exec->create; 159 my $quoter = Net::OpenSSH::ShellQuoter->quoter( $exec->shell->name ); 160 161 my $_cmd_str = "$cmd " . join( " ", map { $quoter->quote($_) } @args ); 162 i_run $_cmd_str, nohup => 1; 163} 164 1651; 166