Sponsoring The Perl Toolchain Summit 2025: Help make this important event another success Learn more

#
# (c) Jan Gehring <jan.gehring@gmail.com>
#
use v5.12.5;
our $VERSION = '1.16.0'; # VERSION
require Exporter;
use base qw(Exporter);
use vars qw(@EXPORT);
use Carp;
require Rex::Commands;
require Rex::Config;
@EXPORT = qw(upload_and_run i_run i_exec i_exec_nohup);
sub upload_and_run {
my ( $template, %option ) = @_;
my $rnd_file = get_tmp_file;
my $fh = Rex::Interface::File->create;
$fh->open( ">", $rnd_file );
$fh->write($template);
$fh->close;
my $fs = Rex::Interface::Fs->create;
$fs->chmod( 755, $rnd_file );
my @argv;
my $command = $rnd_file;
if ( exists $option{with} ) {
$command = Rex::Config->get_executor_for( $option{with} ) . " $command";
}
if ( exists $option{args} ) {
$command .= join( " ", @{ $option{args} } );
}
return i_run("$command 2>&1");
}
# internal run command, doesn't get reported
sub i_run {
my $cmd = shift;
my ( $code, $option );
$option = {};
if ( ref $_[0] eq "CODE" ) {
$code = shift;
}
if ( scalar @_ > 0 ) {
$option = {@_};
}
$option->{valid_retval} ||= [0];
$option->{fail_ok} //= 0;
if ( $option->{no_stderr} ) {
$cmd = "$cmd 2>/dev/null";
}
if ( $option->{stderr_to_stdout} ) {
$cmd = "$cmd 2>&1";
}
if ( ref $option->{valid_retval} ne "ARRAY" ) {
$option->{valid_retval} = [ $option->{valid_retval} ];
}
my $is_no_hup = 0;
my $tmp_output_file = get_tmp_file();
if ( exists $option->{nohup} && $option->{nohup} ) {
$cmd = "nohup $cmd >$tmp_output_file";
delete $option->{nohup};
$is_no_hup = 1;
}
my $path;
if ( !Rex::Config->get_no_path_cleanup() ) {
$path = join( ":", Rex::Config->get_path() );
}
my $exec = Rex::Interface::Exec->create;
my ( $out, $err ) = $exec->exec( $cmd, $path, $option );
my $ret_val = $?;
chomp $out if $out;
chomp $err if $err;
$Rex::Commands::Run::LAST_OUTPUT = [ $out, $err ];
$out ||= "";
$err ||= "";
if ( scalar( grep { $_ == $ret_val } @{ $option->{valid_retval} } ) == 0 ) {
if ( !$option->{fail_ok} ) {
Rex::Logger::debug("Error executing `$cmd`: ");
Rex::Logger::debug("STDOUT:");
Rex::Logger::debug($out);
Rex::Logger::debug("STDERR:");
Rex::Logger::debug($err);
if ($is_no_hup) {
$out = $exec->exec("cat $tmp_output_file ; rm -f $tmp_output_file");
$Rex::Commands::Run::LAST_OUTPUT = [$out];
$? = $ret_val;
}
confess("Error during `i_run`");
}
}
if ($code) {
return &$code( $out, $err );
}
if (wantarray) {
return split( /\r?\n/, $out );
}
if ($is_no_hup) {
$out = $exec->exec("cat $tmp_output_file ; rm -f $tmp_output_file");
$Rex::Commands::Run::LAST_OUTPUT = [$out];
$? = $ret_val;
}
return $out;
}
sub i_exec {
my ( $cmd, @args ) = @_;
my $exec = Rex::Interface::Exec->create;
my $quoter = Net::OpenSSH::ShellQuoter->quoter( $exec->shell->name );
my $_cmd_str = "$cmd " . join( " ", map { $quoter->quote($_) } @args );
i_run $_cmd_str;
}
sub i_exec_nohup {
my ( $cmd, @args ) = @_;
my $exec = Rex::Interface::Exec->create;
my $quoter = Net::OpenSSH::ShellQuoter->quoter( $exec->shell->name );
my $_cmd_str = "$cmd " . join( " ", map { $quoter->quote($_) } @args );
i_run $_cmd_str, nohup => 1;
}
1;