Rex::Commands(3pm)

✨ Rex::Commands ✨

okay bestie, so you've found Rex::Commands β€” the absolute mothership of the Rex::Commands manual page (it's Rex::Commands(3pm), User Contributed Perl Documentation, iykyk). This is literally the core commands module. Everything else in Rex kinda orbits around this one. πŸ’–


πŸ’« NAME πŸ’«

Rex::Commands β€” all the basic commands, periodt.


🌸 DESCRIPTION 🌸

This module is the core commands module. Like… the main character. Nothing else to say, she said it herself. πŸ‘‘


✨ SYNOPSIS ✨

here's the vibe in code form:

desc "Task description";

task "taskname", sub { ... };
task "taskname", "server1", ..., "server20", sub { ... };

group "group" => "server1", "server2", ...;

user "user";

password "password";

environment live => sub {
  user "root";
  password "foobar";
  pass_auth;
  group frontend => "www01", "www02";
};

πŸŽ€ COMMANDLIST πŸŽ€

the whole squad, fr fr:

  • Augeas config file management β€” Rex::Commands::Augeas
  • Cloud Management β€” Rex::Commands::Cloud
  • Cron Management β€” Rex::Commands::Cron
  • Database Commands β€” Rex::Commands::DB
  • SCP Up- and Download β€” Rex::Commands::Upload, Rex::Commands::Download
  • File Manipulation β€” Rex::Commands::File
  • Filesystem Manipulation β€” Rex::Commands::Fs
  • Information Gathering β€” Rex::Commands::Gather
  • Manipulation of /etc/hosts β€” Rex::Commands::Host
  • Get an inventory of your Hardware β€” Rex::Commands::Inventory
  • Manage your iptables rules β€” Rex::Commands::Iptables
  • Kernel Commands β€” Rex::Commands::Kernel
  • LVM Commands β€” Rex::Commands::LVM
  • MD5 checksums β€” Rex::Commands::MD5
  • Network commands β€” Rex::Commands::Network
  • Notify resources to execute β€” Rex::Commands::Notify
  • Package Commands β€” Rex::Commands::Pkg
  • Partition your storage device(s) β€” Rex::Commands::Partition
  • Configure packages (via debconf) β€” Rex::Commands::PkgConf
  • Process Management β€” Rex::Commands::Process
  • Rsync Files β€” Rex::Commands::Rsync
  • Run Remote Commands β€” Rex::Commands::Run
  • Source control via Subversion/Git β€” Rex::Commands::SCM
  • Manage System Services (sysvinit) β€” Rex::Commands::Service
  • Simple TCP/alive checks β€” Rex::Commands::SimpleCheck
  • Sync directories β€” Rex::Commands::Sync
  • Sysctl Commands β€” Rex::Commands::Sysctl
  • Live Tail files β€” Rex::Commands::Tail
  • Upload local file to remote server β€” Rex::Commands::Upload
  • Manage user and group accounts β€” Rex::Commands::User
  • Manage your virtual environments β€” Rex::Commands::Virtualization

πŸ¦‹ EXPORTED FUNCTIONS πŸ¦‹

🧚 no_ssh([$task])

bestie, this one turns OFF ssh. for all your tasks, or just one specific task if you're feeling selective.

If you want to kill the ssh connection for your complete set of tasks β€” like, say, you're only here for libVirt β€” you drop this in the main section of your Rexfile:

no_ssh;

But if it's just one task that doesn't need ssh, you put no_ssh right in front of the task definition. so cute, so simple:

no_ssh task "mytask", "myserver", sub {
  say "Do something without a ssh connection";
};

πŸŽ€ task($name [, @servers], $funcref)

This function creates a new task. three whole flavors, ok?

Create a local task (a server independent task):

task "mytask", sub {
  say "Do something";
};
If you call this task with (R)?ex it will run on your local machine. You can explicitly run this task on other machines if you specify the -H command line parameter.

Create a server bound task:

task "mytask", "server1", sub {
  say "Do something";
};

You can also specify more than one server. go off:

task "mytask", "server1", "server2", "server3", sub {
  say "Do something";
};

Or you can use some expressions to define more than one server. the range syntax is giving efficiency:

task "mytask", "server[1..3]", sub {
  say "Do something";
};
If you want, you can overwrite the servers with the -H command line parameter.

Create a group bound task.

You can define server groups with the group function:

group "allserver" => "server[1..3]", "workstation[1..10]";

task "mytask", group => "allserver", sub {
  say "Do something";
};

πŸ’œ desc($description)

Sets the description of the task, batch, or environment that comes after it. it's like a lil caption for whatever's next. πŸ’…

desc 'This is the description of the following task';
task 'mytask', sub {
  say 'Do something';
};

desc 'This is the description of the following batch';
batch mybatch => 'task1', 'task2', 'task3';

desc 'This is the description of the following environment';
environment production => sub {
  ...
};

⭐ group($name, @servers)

This function lets you group servers so you don't have to type a novel every time. you're welcome ;-)

group "servergroup", "www1", "www2", "www3", "memcache01", "memcache02", "memcache03";

Or with the expression syntax, which is honestly way less typing:

group "servergroup", "www[1..3]", "memcache[01..03]";

If the use_server_auth feature flag is enabled, you can also specify server options after a server name with a hash reference:

use Rex -feature => ['use_server_auth'];

group "servergroup", "www1" => { user => "other" }, "www2";

These expressions are allowed:

  • \d+..\d+ (range)

The first number is the start and the second number is the end for numbering the servers.

group "name", "www[1..3]"; # www1, www2, www3
  • \d+..\d+/\d+ (range with step)

Just like the range notation, but with an additional "step" defined. If step is omitted, it defaults to 1 (i.e. it behaves like a simple range expression).

group "name", "www[1..5/2]";      # www1, www3, www5
group "name", "www[111..133/11]"; # www111, www122, www133
  • \d+,\d+,\d+ (list)

With this variant you can define fixed values. pick your faves:

group "name", "www[1,3,7,01]"; # www1, www3, www7, www01
  • Mixed list, range and range with step

You can mix the three variants above. yes, all at once, slay:

www[1..3,5,9..21/3]; # www1, www2, www3, www5, www9, www12, www15, www18, www21

πŸ“ batch($name, @tasks)

With the batch function you can call tasks in a batch:

batch "name", "task1", "task2", "task3";

And call it with the -b console parameter:

rex -b name

🌈 user($user)

Set the user for the ssh connection.


🫢 password($password)

Set the password for the ssh connection (or for the private key file).


πŸ’€ auth(for => $entity, %data)

With this command you can set or modify authentication parameters for tasks and groups.

Heads up! Please note this is different than setting authentication details for the members of a host group. If you are looking for that, please check out the group command at https://metacpan.org/pod/Rex::Commands#group.

If you want to set special login information for a group you have to enable at least the 0.31 feature flag, and ensure the group is declared before the auth command.

Command line options to set locality or authentication details are still taking precedence, and may override these settings. so like, the CLI wins, no cap.
# auth for groups

use Rex -feature => ['0.31']; # activate setting auth for a group

group frontends => "web[01..10]";
group backends => "be[01..05]";

auth for => "frontends" =>
           user => "root",
           password => "foobar";

auth for => "backends" =>
           user => "admin",
           private_key => "/path/to/id_rsa",
           public_key => "/path/to/id_rsa.pub",
           sudo => TRUE;

# auth for tasks

task "prepare", group => ["frontends", "backends"], sub {
  # do something
};

auth for => "prepare" =>
           user => "root";

# auth for multiple tasks with regular expression

task "step_1", sub {
 # do something
};

task "step_2", sub {
 # do something
};

auth for => qr/step/ =>
  user     => $user,
  password => $password;

# fallback auth
auth fallback => {
  user        => "fallback_user1",
  password    => "fallback_pw1",
  public_key  => "",
  private_key => "",
}, {
  user        => "fallback_user2",
  password    => "fallback_pw2",
  public_key  => "keys/public.key",
  private_key => "keys/private.key",
  sudo        => TRUE,
};

πŸ”₯ port($port)

Set the port where the ssh server is listening.


πŸŽ€ sudo_password($password)

Set the password for the sudo command.


⏳ timeout($seconds)

Set the timeout for the ssh connection and other network related stuff.


πŸ” max_connect_retries($count)

Set the maximum number of connection retries.


🎲 get_random($count, @chars)

Returns a random string of $count characters on the basis of @chars. lil chaotic generator, love her:

my $rnd = get_random(8, 'a' .. 'z');

🧚 do_task($task)

Call $task from another task. It will establish a new connection to the server defined in $task and then execute $task there. she travels ✈️

task "task1", "server1", sub {
  say "Running on server1";
  do_task "task2";
};

task "task2", "server2", sub {
  say "Running on server2";
};

You may also use an arrayRef for $task if you want to call multiple tasks:

do_task [ qw/task1 task2 task3/ ];

πŸ’– run_task($task_name, %option)

Run a task on a given host. the remote-control energy is real.

my $return = run_task "taskname", on => "192.168.3.56";

Do something on server5 if memory is less than 100 MB free on server3. iconic conditional behavior:

task "prepare", "server5", sub {
  my $free_mem = run_task "get_free_mem", on => "server3";
  if($free_mem < 100) {
    say "Less than 100 MB free mem on server3";
    # create a new server instance on server5 to unload server3
  }
};

task "get_free_mem", sub {
   return memory->{free};
};
If called without a hostname the task is run localy. (yes, "localy", that's the manual's spelling, we respect her πŸ’…)
# this task will run on server5
task "prepare", "server5", sub {
  # this will call task check_something. but this task will run on localhost.
  my $check = run_task "check_something";
}

task "check_something", "server4", sub {
  return "foo";
};

If you want to add custom parameters for the task you can do it this way:

task "prepare", "server5", sub {
 run_task "check_something", on => "foo", params => { param1 => "value1", param2 => "value2" };
};

🌟 run_batch($batch_name, %option)

Run a batch on a given host:

my @return = run_batch "batchname", on => "192.168.3.56";

It calls internally run_task, and passes it any option given. sneaky but efficient.


πŸ”‘ public_key($key)

Set the public key.


πŸ—οΈ private_key($key)

Set the private key.


πŸ“ pass_auth

If you want to use password authentication, then you need to call pass_auth. no call, no auth bestie.

user "root";
password "root";

pass_auth;

πŸ¦‹ key_auth

If you want to use pubkey authentication, then you need to call key_auth:

user "bob";
private_key "/home/bob/.ssh/id_rsa"; # passphrase-less key
public_key "/home/bob/.ssh/id_rsa.pub";

key_auth;

πŸ‘‘ krb5_auth

If you want to use kerberos authentication, then you need to call krb5_auth.

This authentication mechanism is only available if you use Net::OpenSSH.
set connection => "OpenSSH";
user "root";
krb5_auth;

(part 1 done, bestie β€” more of this manual is still coming, don't go anywhere πŸ’–)

πŸ’« parallelism($count)

Okay so this one is the glow-up for running your tasks on a bunch of servers at once β€” it'll execute the tasks in parallel on the given servers, and $count is the thread count to use:

parallelism '2'; # set parallelism to 2

✨ Or, if you wanna be ✨dynamic✨ about it, there's this notation too:

parallelism 'max';     # set parallelism to the number of servers a task is asked to run on
parallelism 'max/3';   # set parallelism to 1/3 of the number of servers
parallelism 'max 10%'; # set parallelism to 10% of the number of servers

Now bestie, listen 🫢 β€” if you pass something it doesn't recognize, or the calculated thread count would come out less than 1, Rex just falls back to using a single thread. No drama, no crash, it just does the quiet thing.


πŸ”Œ proxy_command($cmd)

This sets a proxy command to use for the connection. Heads up though: this is only possible with the OpenSSH connection method. That's a real limitation, not a vibe πŸ’…

set connection => "OpenSSH";
proxy_command "ssh user@jumphost nc %h %p 2>/dev/null";

πŸŽ›οΈ set_distributor($distributor)

This sets the task distribution module. The default is "Base".

The possible values are: Base, Gearman, Parallel_ForkManager.


🧁 template_function(sub { ... })

This sets the template processing function. So basically you can swap out the whole template engine β€” say, over to Template::Toolkit. Customize away, it's giving bespoke πŸ’–


πŸ“ logging

With this function you can define the logging behaviour of (R)?ex. Two flavours, pick your fighter:

Logging to a file

logging to_file => "rex.log";

Logging to syslog

logging to_syslog => $facility;

🧩 needs($package [, @tasks])

With needs you can define dependencies between tasks. The "needed" tasks will be called with the same server configuration as the calling task. Iconic, honestly.

Heads up bestie: needs will not execute before, around and after hooks. Not a bug, just how it is πŸ’€

Depend on all tasks in a given package.

Depend on all tasks in the package MyPkg. All tasks will be called with the server server1.

task "mytask", "server1", sub {
  needs MyPkg;
};

Depend on a single task in a given package.

Depend on the uname task in the package MyPkg. The uname task will be called with the server server1.

task "mytask", "server1", sub {
  needs MyPkg "uname";
};

To call tasks defined in the Rexfile from within a module

task "mytask", "server1", sub {
  needs main "uname";
};

πŸ“¦ include Module::Name

Include a module without registering its tasks. Sneaky, quiet, respectful 😌

include qw/
  Module::One
  Module::Two
/;

🌍 environment($name => $code)

Define an environment! With environments you can use the same task for different hosts. For example, if you want to use the same task on your integration-, test- and production servers. Chef's kiss honestly πŸ‘‘

# define default user/password
user "root";
password "foobar";
pass_auth;

# define default frontend group containing only testwww01.
group frontend => "testwww01";

# define live environment, with different user/password
# and a frontend server group containing www01, www02 and www03.
environment live => sub {
  user "root";
  password "livefoo";
  pass_auth;

  group frontend => "www01", "www02", "www03";
};

# define stage environment with default user and password. but with
# a own frontend group containing only stagewww01.
environment stage => sub {
  group frontend => "stagewww01";
};

task "prepare", group => "frontend", sub {
   say run "hostname";
};

So: calling this task rex prepare will execute on testwww01. Calling this task with rex -E live prepare will execute on www01, www02, www03. And calling this task rex -E stage prepare will execute on stagewww01. Three vibes, one task, no copy-pasting 🌈

You can also call the function within a task to get the current environment:

task "prepare", group => "frontend", sub {
  if(environment() eq "dev") {
    say "i'm in the dev environment";
  }
};

And if no -E option is passed on the command line, the default environment (named 'default') will be used. Periodt.


🏠 LOCAL(&)

With the LOCAL function you can do local commands within a task that is defined to work on remote servers. So you're like "okay but this one bit, run it right here on my machine" πŸ’…

task "mytask", "server1", "server2", sub {
   # this will call 'uptime' on the servers 'server1' and 'server2'
   say run "uptime";

   # this will call 'uptime' on the local machine.
   LOCAL {
     say run "uptime";
   };
};

πŸ›€οΈ path(@path)

Set the execution path for all commands.

path "/bin", "/sbin", "/usr/bin", "/usr/sbin", "/usr/pkg/bin", "/usr/pkg/sbin";

It's a convenience wrapper for the set_path configuration option β€” cute, efficient, we love her πŸŽ€


βš™οΈ set($key, $value)

Set a configuration parameter. These variables can be used in templates as well. Double duty, main character energy.

set database => "db01";

task "prepare", sub {
  my $db = get "database";
};

Or in a template:

DB: <%= $::database %>

The following list of configuration parameters are Rex specific:


πŸ” get($key, $value)

Get a configuration parameter. The twin flame of set πŸ’ž

set database => "db01";

task "prepare", sub {
  my $db = get "database";
};

Or in a template:

DB: <%= $::database %>

βͺ before($task => sub {})

Run code before executing the specified task.

The task name is a regular expression to find all tasks with a matching name. And there's a special task name, 'ALL', which you can use to run code before all tasks. Slay.

If called repeatedly, each sub will be appended to a list of 'before' functions. They stack, babes.

In this hook you can overwrite the server to which the task will connect to. The second argument is a reference to the server object that will be used for the connection. Powerful stuff πŸ”₯

Please note, this must come after the definition of the specified task.
 before mytask => sub {
  my ($server, $server_ref, $cli_args) = @_;
  run "vzctl start vm$server";
 };

⏩ after($task => sub {})

Run code after executing the specified task.

The task name is a regular expression to find all tasks with a matching name. The special task name 'ALL' can be used to run code after all tasks.

If called repeatedly, each sub will be appended to a list of 'after' functions.

Please note, this must come after the definition of the specified task.
 after mytask => sub {
  my ($server, $failed, $cli_args) = @_;
  if($failed) { say "Connection to $server failed."; }

  run "vzctl stop vm$server";
 };

πŸ”„ around($task => sub {})

Run code around the specified task β€” that is, both before and after executing it. Two-for-one πŸŽ€

The task name is a regular expression to find all tasks with a matching name. The special task name 'ALL' can be used to run code around all tasks.

If called repeatedly, each sub will be appended to a list of 'around' functions.

In this hook you can overwrite the server to which the task will connect to. The second argument is a reference to the server object that will be used for the connection.

Please note, this must come after the definition of the specified task.
 around mytask => sub {
  my ($server, $server_ref, $cli_args, $position) = @_;

  unless($position) {
    say "Before Task\n";
  }
  else {
    say "After Task\n";
  }
 };

πŸš€ before_task_start($task => sub {})

Run code before executing the specified task. This one gets executed only once for a task β€” one shot, no repeats ✨

The task name is a regular expression to find all tasks with a matching name. The special task name 'ALL' can be used to run code before all tasks.

If called repeatedly, each sub will be appended to a list of 'before_task_start' functions.

Please note, this must come after the definition of the specified task.
 before_task_start mytask => sub {
   # do some things
 };

🏁 after_task_finished($task => sub {})

Run code after the task is finished (and after the ssh connection is terminated). This also gets executed only once for a task.

The task name is a regular expression to find all tasks with a matching name. The special task name 'ALL' can be used to run code after all tasks.

If called repeatedly, each sub will be appended to a list of 'after_task_finished' functions.

Please note, this must come after the definition of the specified task.
 after_task_finished mytask => sub {
   # do some things
 };

🎨 logformat($format)

You can define the logging format with the following parameters:

  • %D β€” Appends the current date yyyy-mm-dd HH:mm:ss
  • %h β€” The target host
  • %p β€” The pid of the running process
  • %l β€” Loglevel (INFO or DEBUG)
  • %s β€” The Logstring

Default is: [%D] %l - %s


πŸ”— connection

This function returns the current connection object.

task "foo", group => "baz", sub {
  say "Current Server: " . connection->server;
};

πŸ—„οΈ cache

This function returns the current cache object.


πŸ“Š profiler

Returns the profiler object for the current connection.


πŸ“’ report($switch, $type)

This function will initialize the reporting.

report -on => "YAML";

πŸ“œ source_global_profile(0|1)

If this option is set, every run() command will first source /etc/profile before getting executed. Every single one. Consistency queen πŸ‘‘


πŸ–¨οΈ last_command_output

This function returns the output of the last "run" command.

On a debian system this example will return the output of apt-get install foobar.

task "mytask", "myserver", sub {
  install "foobar";
  say last_command_output();
};

🍰 case($compare, $option)

This is a function to compare a string with some given options. Very "let me handle this" energy.

task "mytask", "myserver", sub {
  my $ntp_service = case operating_system, {
                Debian  => "ntp",
                default => "ntpd",
              };

  my $ntp_service = case operating_system, {
                qr{debian}i => "ntp",
                default    => "ntpd",
              };

  my $ntp_service = case operating_system, {
                qr{debian}i => "ntp",
                default    => sub { return "foo"; },
              };
};

πŸƒ set_executor_for($type, $executor)

Set the executor for a special type. This is primarily used for the upload_and_run helper function.

set_executor_for perl => "/opt/local/bin/perl";

πŸ“ tmp_dir($tmp_dir)

Set the tmp directory on the remote host to store temporary files.


πŸ”¬ inspect($varRef)

This function dumps the contents of a variable to STDOUT. Peek behind the curtain bestie 🫣

task "mytask", "myserver", sub {
  my $myvar = {
    name => "foo",
    sys  => "bar",
  };

  inspect $myvar;
};

πŸ’¬ sayformat($format)

You can define the format of the say() function.

  • %D β€” The current date yyyy-mm-dd HH:mm:ss
  • %h β€” The target host
  • %p β€” The pid of the running process
  • %s β€” The Logstring

You can also define the following values:

  • default β€” the default behaviour.
  • asis β€” will print every single parameter in its own line. This is useful if you want to print the output of a command.

And that's the whole page, bestie, we made it to the end together πŸ₯ΉπŸ«Ά This doc is from perl v5.40.1, dated 2025-10-03, and it's the Rex::Commands(3pm) manpage β€” go forth and automate something iconic βœ¨πŸ’…

πŸ“¦ where this page comes from