/lib/Rex/Commands/Run.pm

https://github.com/pplu/Rex · Perl · 195 lines · 136 code · 53 blank · 6 comment · 21 complexity · 35070eb887c78f1caaed9f1bb2dd0cf6 MD5 · raw file

  1. #
  2. # (c) Jan Gehring <jan.gehring@gmail.com>
  3. #
  4. # vim: set ts=3 sw=3 tw=0:
  5. # vim: set expandtab:
  6. =head1 NAME
  7. Rex::Commands::Run - Execute a remote command
  8. =head1 DESCRIPTION
  9. With this module you can run a command.
  10. =head1 SYNOPSIS
  11. my $output = run "ls -l";
  12. sudo "id";
  13. =head1 EXPORTED FUNCTIONS
  14. =over 4
  15. =cut
  16. package Rex::Commands::Run;
  17. use strict;
  18. use warnings;
  19. require Exporter;
  20. use Data::Dumper;
  21. use Rex;
  22. use Rex::Logger;
  23. use Rex::Helper::SSH2;
  24. use Rex::Helper::SSH2::Expect;
  25. use Rex::Config;
  26. BEGIN {
  27. if($^O !~ m/^MSWin/) {
  28. eval "use Expect";
  29. }
  30. else {
  31. Rex::Logger::debug("Running under windows, Expect not supported.");
  32. }
  33. }
  34. use vars qw(@EXPORT);
  35. use base qw(Exporter);
  36. @EXPORT = qw(run can_run sudo);
  37. =item run($command)
  38. This function will execute the given command and returns the output.
  39. task "uptime", "server01", sub {
  40. say run "uptime";
  41. };
  42. =cut
  43. sub run {
  44. my $cmd = shift;
  45. Rex::Logger::debug("Running command: $cmd");
  46. my @ret = ();
  47. my $out;
  48. # no can_run($cmd) if there are parameters
  49. if(my $ssh = Rex::is_ssh()) {
  50. my @paths = Rex::Config->get_path;
  51. my $path="";
  52. if(@paths) {
  53. $path = "PATH=" . join(":", @paths);
  54. }
  55. $out = net_ssh2_exec($ssh, "LC_ALL=C $path " . $cmd);
  56. } else {
  57. if($^O =~ m/^MSWin/) {
  58. $out = qx{$cmd};
  59. }
  60. else {
  61. $out = qx{LC_ALL=C $cmd};
  62. }
  63. }
  64. Rex::Logger::debug($out);
  65. Rex::Logger::debug("Returncode: $?");
  66. chomp $out;
  67. if(wantarray) {
  68. return split(/\n/, $out);
  69. }
  70. return $out;
  71. }
  72. =item can_run($command)
  73. This function checks if a command is in the path or is available.
  74. task "uptime", sub {
  75. if(can_run "uptime") {
  76. say run "uptime";
  77. }
  78. };
  79. =cut
  80. sub can_run {
  81. my $cmd = shift;
  82. if($^O =~ m/^MSWin/) {
  83. return 1;
  84. }
  85. my @ret = run "which $cmd";
  86. if($? != 0) { return 0; }
  87. if( grep { /^no.*in/ } @ret ) {
  88. return 0;
  89. }
  90. return 1;
  91. }
  92. =item sudo($command)
  93. Run $command with I<sudo>. Define the password for sudo with I<sudo_password>.
  94. task "eth1-down", sub {
  95. sudo "ifconfig eth1 down";
  96. };
  97. =cut
  98. sub sudo {
  99. my ($cmd) = @_;
  100. my $exp;
  101. my $timeout = Rex::Config->get_timeout;
  102. my $sudo_password = Rex::Config->get_sudo_password;
  103. if(my $ssh = Rex::is_ssh()) {
  104. $exp = Rex::Helper::SSH2::Expect->new($ssh);
  105. }
  106. else {
  107. if($^O =~ m/^MSWin/) {
  108. die("Expect not woring on windows");
  109. }
  110. else {
  111. $exp = Expect->new();
  112. }
  113. }
  114. $exp->log_stdout(0);
  115. my $cmd_out = "";
  116. $exp->log_file(sub {
  117. my ($str) = @_;
  118. $cmd_out .= $str;
  119. });
  120. $exp->spawn("sudo", $cmd);
  121. $exp->expect($timeout, [
  122. qr/Password:|\[sudo\] password for [^:]+:/i => sub {
  123. Rex::Logger::debug("Sending password");
  124. my ($exp, $line) = @_;
  125. $exp->send($sudo_password . "\n");
  126. unless(ref($exp) eq "Rex::Helper::SSH2::Expect") {
  127. exp_continue();
  128. }
  129. },
  130. ]);
  131. unless(ref($exp) eq "Rex::Helper::SSH2::Expect") {
  132. $exp->soft_close;
  133. }
  134. chomp $cmd_out;
  135. if(wantarray) {
  136. return split(/\n/, $cmd_out);
  137. }
  138. return $cmd_out;
  139. }
  140. =back
  141. =cut
  142. 1;