NAME

Remote::Perl - Run Perl scripts on remote machines over any pipe transport

SYNOPSIS

$ remperl hostx script.pl
$ remperl hostx -e 'print "hello\n"'

use Remote::Perl;

my $r = Remote::Perl->new(
    cmd     => ['ssh', 'hostx', 'perl'],
);

# Run a script file
my ($rc, $msg) = $r->run_file('myscript.pl');
die "failed: $msg\n" if $rc;

# Run inline code with callbacks and arguments
$r->run_code('print "Hello, $_\n" for @ARGV',
    args      => ['world'],
    on_stdout => sub { print STDOUT $_[0] },
    on_stderr => sub { print STDERR $_[0] },
    stdin     => \*STDIN,
);

$r->disconnect;

DESCRIPTION

Remote::Perl connects to a remote Perl interpreter through an arbitrary pipe command, bootstraps a self-contained protocol client on the remote end, and executes Perl code there. STDOUT and STDERR from the remote script are relayed in real time; local STDIN is forwarded on demand.

When module serving is enabled (serve => 1), missing modules are fetched from the local machine's @INC on demand. The remote machine needs no pre-installed dependencies beyond a bare Perl interpreter.

Remote::Perl ships with the command line tool remperl that exposes most functionality of the module.

CONSTRUCTOR

new(%args)

my $r = Remote::Perl->new(
    cmd    => ['ssh', 'hostx', 'perl'],   # required
    window => 65_536,                     # flow-control window in bytes (default: 65536)
    serve  => 1,                          # enable module serving (default: 0)
    inc    => \@dirs,                     # local @INC for module serving (default: \@INC)
);

Spawns the pipe command, bootstraps the remote Perl client, and performs the protocol handshake. Dies on failure.

serve and inc work together: serve => 1 installs a remote @INC hook that requests modules from the local side; inc supplies the local directories to search (defaults to \@INC if omitted).

METHODS

run_code($source, %opts)

my $rc          = $r->run_code($source);
my ($rc, $msg)  = $r->run_code($source, %opts);

Executes $source as Perl code on the remote side. In scalar context returns the exit code. In list context also returns the error message (empty string on clean exit, the die message on failure).

Options:

on_stdout => sub { my ($chunk) = @_; ... }

Called with each chunk of stdout data produced by the remote script.

on_stderr => sub { my ($chunk) = @_; ... }

Called with each chunk of stderr data produced by the remote script.

stdin => $fh_or_string

Data to supply as the remote script's STDIN. May be a filehandle (must have a real file descriptor) or a plain string. Omit or pass undef to supply no stdin (the remote script sees immediate EOF).

args => \@args

Values to place in the remote @ARGV before execution.

run_file($path, %opts)

my ($rc, $msg) = $r->run_file('myscript.pl', %opts);

Reads the local file at $path and runs its contents as Perl source on the remote side. Accepts the same options as "run_code".

send_signal($signame)

$r->send_signal('INT');

Sends a signal by name to the remote script's executor process via the protocol. The signal is delivered regardless of the transport (SSH, Docker, etc.) because it travels over the protocol pipe rather than as a Unix signal to the transport process.

disconnect

$r->disconnect;

Sends BYE, waits for the remote to acknowledge, and closes the transport. Called automatically on object destruction if not already disconnected.

SECURITY

See "SECURITY" in remperl for security considerations.

REQUIREMENTS

Perl 5.36 or later on both local and remote machines. No non-core modules are required on either side.

BUGS

__DATA__ and __END__ sections in scripts passed to "run_code" or "run_file" are not currently supported. The code before the marker executes correctly, but <DATA> reads will not work.

SEE ALSO

remperl -- the command-line interface.

AUTHOR

Pied Crow <crow@cpan.org>

LICENSE

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.