.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Rex::Commands::Run 3pm" .TH Rex::Commands::Run 3pm "2020-09-18" "perl v5.28.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Rex::Commands::Run \- Execute a remote command .SH "DESCRIPTION" .IX Header "DESCRIPTION" With this module you can run a command. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& my $output = run "ls \-l"; \& sudo "id"; .Ve .SH "EXPORTED FUNCTIONS" .IX Header "EXPORTED FUNCTIONS" .ie n .SS "run($command [, $callback], %options)" .el .SS "run($command [, \f(CW$callback\fP], \f(CW%options\fP)" .IX Subsection "run($command [, $callback], %options)" .ie n .SS "run($command, $arguments, %options)" .el .SS "run($command, \f(CW$arguments\fP, \f(CW%options\fP)" .IX Subsection "run($command, $arguments, %options)" This form will execute \f(CW$command\fR with the given \f(CW$arguments\fR. \&\f(CW$arguments\fR must be an array reference. The arguments will be quoted. .PP .Vb 2 \& run "ls", ["\-l", "\-t", "\-r", "\-a"]; \& run "ls", ["/tmp", "\-l"], auto_die => TRUE; .Ve .ie n .SS "run($command_description, command => $command, %options)" .el .SS "run($command_description, command => \f(CW$command\fP, \f(CW%options\fP)" .IX Subsection "run($command_description, command => $command, %options)" This function will execute the given command and returns the output. In scalar context it returns the raw output as is, and in list context it returns the list of output lines. The exit value of the command is stored in the $? variable. .PP .Vb 8 \& task "uptime", "server01", sub { \& say run "uptime"; \& run "uptime", sub { \& my ($stdout, $stderr) = @_; \& my $server = Rex::get_current_connection()\->{server}; \& say "[$server] $stdout\en"; \& }; \& }; .Ve .PP Supported options are: .PP .Vb 10 \& cwd => $path \& sets the working directory of the executed command to $path \& only_if => $condition_command \& executes the command only if $condition_command completes successfully \& unless => $condition_command \& executes the command unless $condition_command completes successfully \& only_notified => TRUE \& queues the command, to be executed upon notification (see below) \& env => { var1 => $value1, ..., varN => $valueN } \& sets environment variables in the environment of the command \& timeout => value \& sets the timeout for the command to be run \& auto_die => TRUE \& die if the command returns with a non\-zero exit code \& it can be set globally via the exec_autodie feature flag \& command => $command_to_run \& if set, run tries to execute the specified command and the first argument \& becomes an identifier for the run block (e.g. to be triggered with notify) \& creates => $file_to_create \& tries to create $file_to_create upon execution \& skips execution if the file already exists \& continuous_read => $callback \& calls $callback subroutine reference for each line of the command\*(Aqs output, \& passing the line as an argument .Ve .PP Examples: .PP If you only want to run a command in special cases, you can queue the command and notify it when you want to run it. .PP .Vb 4 \& task "prepare", sub { \& run "extract\-something", \& command => "tar \-C /foo \-xzf /tmp/foo.tgz", \& only_notified => TRUE; \& \& # some code ... \& \& notify "run", "extract\-something"; # now the command gets executed \& }; .Ve .PP If you only want to run a command if another command succeeds or fails, you can use \&\fIonly_if\fR or \fIunless\fR option. .PP .Vb 2 \& run "some\-command", \& only_if => "ps \-ef | grep \-q httpd"; # only run if httpd is running \& \& run "some\-other\-command", \& unless => "ps \-ef | grep \-q httpd"; # only run if httpd is not running .Ve .PP If you want to set custom environment variables you can do it like this: .PP .Vb 1 \& run "my_command", \& \& env => { \& env_var_1 => "the value for 1", \& env_var_2 => "the value for 2", \& }; .Ve .PP If you want to end the command upon receiving a certain output: run \*(L"my_command\*(R", end_if_matched => qr/PATTERN/; .SS "can_run($command)" .IX Subsection "can_run($command)" This function checks if a command is in the path or is available. You can specify multiple commands, the first command found will be returned. .PP .Vb 5 \& task "uptime", sub { \& if( my $cmd = can_run("uptime", "downtime") ) { \& say run $cmd; \& } \& }; .Ve .SS "sudo" .IX Subsection "sudo" Run a single command, a code block, or all commands with \f(CW\*(C`sudo\*(C'\fR. You need perl to be available on the remote systems to use \f(CW\*(C`sudo\*(C'\fR. .PP Depending on your remote sudo configuration, you may need to define a sudo password with \fIsudo_password\fR first: .PP .Vb 1 \& sudo_password \*(Aqmy_sudo_password\*(Aq; # hardcoding .Ve .PP Or alternatively, since Rexfile is plain perl, you can read the password from terminal at the start: .PP .Vb 1 \& use Term::ReadKey; \& \& print \*(AqI need sudo password: \*(Aq; \& ReadMode(\*(Aqnoecho\*(Aq); \& sudo_password ReadLine(0); \& ReadMode(\*(Aqrestore\*(Aq); .Ve .PP Similarly, it is also possible to read it from a secret file, database, etc. .PP You can turn sudo on globally with: .PP .Vb 1 \& sudo TRUE; # run _everything_ with sudo .Ve .PP To run only a specific command with sudo, use : .PP .Vb 2 \& say sudo \*(Aqid\*(Aq; # passing a remote command directly \& say sudo { command => \*(Aqid\*(Aq }; # passing anonymous hashref \& \& say sudo { command => \*(Aqid\*(Aq, user => \*(Aqdifferent\*(Aq }; # run a single command with sudo as different user \& \& # running a single command with sudo as different user, and \`cd\` to another directory too \& say sudo { command => \*(Aqid\*(Aq, user => \*(Aqdifferent\*(Aq, cwd => \*(Aq/home/different\*(Aq }; .Ve .PP To run multiple commands with \f(CW\*(C`sudo\*(C'\fR, either use an anonymous code reference directly: .PP .Vb 4 \& sudo sub { \& service \*(Aqnginx\*(Aq => \*(Aqrestart\*(Aq; \& say run \*(Aqid\*(Aq; \& }; .Ve .PP or pass it via \f(CW\*(C`command\*(C'\fR (optionally along a different user): .PP .Vb 7 \& sudo { \& command => sub { \& say run \*(Aqid\*(Aq; \& say run \*(Aqpwd\*(Aq, cwd => \*(Aq/home/different\*(Aq; \& }, \& user => \*(Aqdifferent\*(Aq, \& }; .Ve .PP \&\fBNote\fR that some users receive the error \f(CW\*(C`sudo: sorry, you must have a tty to run sudo\*(C'\fR. In this case you have to disable \f(CW\*(C`requiretty\*(C'\fR for this user. You can do this in your sudoers file with the following code: .PP .Vb 1 \& Defaults:$username !requiretty .Ve