| 1 |
NAME |
| 2 |
AnyEvent::Fork::Remote - remote processes with AnyEvent::Fork interface |
| 3 |
|
| 4 |
THE API IS NOT FINISHED, CONSIDER THIS A BETA RELEASE |
| 5 |
|
| 6 |
SYNOPSIS |
| 7 |
use AnyEvent; |
| 8 |
use AnyEvent::Fork::Remote; |
| 9 |
|
| 10 |
my $rpc = AnyEvent::Fork::Remote |
| 11 |
->new_execp ("ssh", "ssh", "othermachine", "perl") |
| 12 |
->require ("MyModule") |
| 13 |
->run ("MyModule::run", my $cv = AE::cv); |
| 14 |
|
| 15 |
my $fh = $cv->recv; |
| 16 |
|
| 17 |
DESCRIPTION |
| 18 |
Despite what the name of this module might suggest, it doesn't actually |
| 19 |
create remote processes for you. But it does make it easy to use them, |
| 20 |
once you have started them. |
| 21 |
|
| 22 |
This module implements a very similar API as AnyEvent::Fork. In fact, |
| 23 |
similar enough to require at most minor modifications to support both at |
| 24 |
the same time. For example, it works with AnyEvent::Fork::RPC and |
| 25 |
AnyEvent::Fork::Pool. |
| 26 |
|
| 27 |
The documentation for this module will therefore only document the parts |
| 28 |
of the API that differ between the two modules. |
| 29 |
|
| 30 |
SUMMARY OF DIFFERENCES |
| 31 |
Here is a short summary of the main differences between AnyEvent::Fork |
| 32 |
and this module: |
| 33 |
|
| 34 |
* "send_fh" is not implemented and will fail |
| 35 |
|
| 36 |
* the child-side "run" function must read from STDIN and write to |
| 37 |
STDOUT |
| 38 |
|
| 39 |
* "fork" does not actually fork, but will create a new process |
| 40 |
|
| 41 |
EXAMPLE |
| 42 |
This example uses a local perl (because that is likely going to work |
| 43 |
without further setup) and the AnyEvent::Fork::RPC to create simple |
| 44 |
worker process. |
| 45 |
|
| 46 |
First load the modules we are going to use: |
| 47 |
|
| 48 |
use AnyEvent; |
| 49 |
use AnyEvent::Fork::Remote; |
| 50 |
use AnyEvent::Fork::RPC; |
| 51 |
|
| 52 |
Then create, configure and run the process: |
| 53 |
|
| 54 |
my $rpc = AnyEvent::Fork::Remote |
| 55 |
->new_execp ("perl", "perl") |
| 56 |
->eval (' |
| 57 |
sub myrun { |
| 58 |
"this is process $$, and you passed <@_>" |
| 59 |
} |
| 60 |
') |
| 61 |
->AnyEvent::Fork::RPC::run ("myrun"); |
| 62 |
|
| 63 |
We use "new_execp" to execute the first perl found in the PATH. You'll |
| 64 |
have to make sure there is one for this to work. The perl does not |
| 65 |
actually have to be the same perl as the one running the example, and it |
| 66 |
doesn't need to have any modules installed. |
| 67 |
|
| 68 |
The reason we have to specif< "perl" twice is that the first argument to |
| 69 |
"new_execp" (and also "new_exec") is the program name or path, while the |
| 70 |
remaining ones are the arguments, and the first argument passed to a |
| 71 |
program is the program name, so it has to be specified twice. |
| 72 |
|
| 73 |
Finally, the standard example, send some numbers to the remote function, |
| 74 |
and print whatever it returns: |
| 75 |
|
| 76 |
my $cv = AE::cv; |
| 77 |
|
| 78 |
for (1..10) { |
| 79 |
$cv->begin; |
| 80 |
$rpc->($_, sub { |
| 81 |
print "remote function returned: $_[0]\n"; |
| 82 |
$cv->end; |
| 83 |
}); |
| 84 |
} |
| 85 |
|
| 86 |
$cv->recv; |
| 87 |
|
| 88 |
Now, executing perl in the PATH isn't very interesting - you could have |
| 89 |
done the same with AnyEvent::Fork, and it might even be more efficient. |
| 90 |
|
| 91 |
The power of this module is that the perl doesn't need to run on the |
| 92 |
local box, you could simply substitute another command, such as ssh |
| 93 |
remotebox perl: |
| 94 |
|
| 95 |
my $rpc = AnyEvent::Fork::Remote |
| 96 |
->new_execp ("ssh", "ssh", "remotebox", "perl") |
| 97 |
|
| 98 |
And if you want to use a specific path for ssh, use "new_exec": |
| 99 |
|
| 100 |
my $rpc = AnyEvent::Fork::Remote |
| 101 |
->new_exec ("/usr/bin/ssh", "ssh", "remotebox", "perl") |
| 102 |
|
| 103 |
Of course, it doesn't really matter to this module how you construct |
| 104 |
your perl processes, what matters is that somehow, you give it a file |
| 105 |
handle connected to the new perls STDIN and STDOUT. |
| 106 |
|
| 107 |
PARENT PROCESS USAGE |
| 108 |
my $proc = new_exec AnyEvent::Fork::Remote $path, @args... |
| 109 |
Creates a new "AnyEvent::Fork::Remote" object. Unlike |
| 110 |
AnyEvent::Fork, processes are only created when "run" is called, |
| 111 |
every other method call is is simply recorded until then. |
| 112 |
|
| 113 |
Each time a new process is needed, it executes $path with the given |
| 114 |
arguments (the first array member must be the program name, as with |
| 115 |
the "exec" function with explicit PROGRAM argument) and both "STDIN" |
| 116 |
and "STDOUT" connected to a communications socket. No input must be |
| 117 |
consumed by the command before perl is started, and no output should |
| 118 |
be generated. |
| 119 |
|
| 120 |
The program *must* invoke perl somehow, with STDIN and STDOUT |
| 121 |
intact, without specifying anything to execute (no script file name, |
| 122 |
no "-e" switch etc.). |
| 123 |
|
| 124 |
Here are some examples to give you an idea: |
| 125 |
|
| 126 |
# just "perl" |
| 127 |
$proc = new_exec AnyEvent::Fork::Remote |
| 128 |
"/usr/bin/perl", "perl"; |
| 129 |
|
| 130 |
# rsh othernode exec perl |
| 131 |
$proc = new_exec AnyEvent::Fork::Remote |
| 132 |
"/usr/bin/rsh", "rsh", "othernode", "exec perl"; |
| 133 |
|
| 134 |
# a complicated ssh command |
| 135 |
$proc = new_exec AnyEvent::Fork::Remote |
| 136 |
"/usr/bin/ssh", |
| 137 |
qw(ssh -q |
| 138 |
-oCheckHostIP=no -oTCPKeepAlive=yes -oStrictHostKeyChecking=no |
| 139 |
-oGlobalKnownHostsFile=/dev/null -oUserKnownHostsFile=/dev/null |
| 140 |
otherhost |
| 141 |
exec perl); |
| 142 |
|
| 143 |
my $proc = new_execp AnyEvent::Fork::Remote $file, @args... |
| 144 |
Just like "new_exec", except that the program is searched in the |
| 145 |
$ENV{PATH} first, similarly to how the shell does it. This makes it |
| 146 |
easier to find e.g. "ssh": |
| 147 |
|
| 148 |
$proc = new_execp AnyEvent::Fork::Remote "ssh", "ssh", "otherhost", "perl"; |
| 149 |
|
| 150 |
my $proc = new AnyEvent::Fork::Remote $create_callback |
| 151 |
Basically the same as "new_exec", but instead of a command to |
| 152 |
execute, it expects a callback which is invoked each time a process |
| 153 |
needs to be created. |
| 154 |
|
| 155 |
The $create_callback is called with another callback as argument, |
| 156 |
and should call this callback with the file handle that is connected |
| 157 |
to a perl process. This callback can be invoked even after the |
| 158 |
$create_callback returns. |
| 159 |
|
| 160 |
Example: emulate "new_exec" using "new". |
| 161 |
|
| 162 |
use AnyEvent::Util; |
| 163 |
use Proc::FastSpawn; |
| 164 |
|
| 165 |
$proc = new AnyEvent::Fork::Remote sub { |
| 166 |
my $done = shift; |
| 167 |
|
| 168 |
my ($a, $b) = AnyEvent::Util::portable_socketpair |
| 169 |
or die; |
| 170 |
|
| 171 |
open my $oldin , "<&0" or die; |
| 172 |
open my $oldout, ">&1" or die; |
| 173 |
|
| 174 |
open STDIN , "<&" . fileno $b or die; |
| 175 |
open STDOUT, ">&" . fileno $b or die; |
| 176 |
|
| 177 |
spawn "/usr/bin/rsh", ["rsh", "othernode", "perl"]; |
| 178 |
|
| 179 |
open STDIN , "<&" . fileno $oldin ; |
| 180 |
open STDOUT, ">&" . fileno $oldout; |
| 181 |
|
| 182 |
$done->($a); |
| 183 |
}; |
| 184 |
|
| 185 |
my $proc = new_from_fh $fh |
| 186 |
Creates an "AnyEvent::Fork::Remote" object from a file handle. This |
| 187 |
file handle must be connected to both STDIN and STDOUT of a perl |
| 188 |
process. |
| 189 |
|
| 190 |
This form might be more convenient than "new" or "new_exec" when |
| 191 |
creating an "AnyEvent::Fork::Remote" object, but the resulting |
| 192 |
object does not support "fork". |
| 193 |
|
| 194 |
$new_proc = $proc->fork |
| 195 |
Quite the same as the same method of AnyEvent::Fork, except that it |
| 196 |
simply clones the object without creating an actual process. |
| 197 |
|
| 198 |
undef = $proc->pid |
| 199 |
The "pid" method always returns "undef" and only exists for |
| 200 |
compatibility with AnyEvent::Fork. |
| 201 |
|
| 202 |
$proc = $proc->send_fh (...) |
| 203 |
Not supported and always croaks. |
| 204 |
|
| 205 |
$proc = $proc->eval ($perlcode, @args) |
| 206 |
Quite the same as the same method of AnyEvent::Fork. |
| 207 |
|
| 208 |
$proc = $proc->require ($module, ...) |
| 209 |
Quite the same as the same method of AnyEvent::Fork. |
| 210 |
|
| 211 |
$proc = $proc->send_arg ($string, ...) |
| 212 |
Quite the same as the same method of AnyEvent::Fork. |
| 213 |
|
| 214 |
$proc->run ($func, $cb->($fh)) |
| 215 |
Very similar to the run method of AnyEvent::Fork. |
| 216 |
|
| 217 |
On the parent side, the API is identical, except that a $cb argument |
| 218 |
of "undef" instead of a valid file handle signals an error. |
| 219 |
|
| 220 |
On the child side, the "communications socket" is in fact just |
| 221 |
*STDIN, and typically can only be read from (this highly depends on |
| 222 |
how the program is created - if you just run perl locally, it will |
| 223 |
work for both reading and writing, but commands such as rsh or ssh |
| 224 |
typically only provide read-only handles for STDIN). |
| 225 |
|
| 226 |
To be portable, if the run function wants to read data that is |
| 227 |
written to $fh in the parent, then it should read from STDIN. If the |
| 228 |
run function wants to provide data that can later be read from $fh, |
| 229 |
then it should write them to STDOUT. |
| 230 |
|
| 231 |
You can write a run function that works with both AnyEvent::Fork and |
| 232 |
this module by checking "fileno $fh". If it is 0 (meaning it is |
| 233 |
STDIN), then you should use it for reading, and STDOUT for writing. |
| 234 |
Otherwise, you should use the file handle for both: |
| 235 |
|
| 236 |
sub run { |
| 237 |
my ($rfh, ...) = @_; |
| 238 |
my $wfh = fileno $rfh ? $rfh : *STDOUT; |
| 239 |
|
| 240 |
# now use $rfh for reading and $wfh for writing |
| 241 |
} |
| 242 |
|
| 243 |
SEE ALSO |
| 244 |
AnyEvent::Fork, the same as this module, for local processes. |
| 245 |
|
| 246 |
AnyEvent::Fork::RPC, to talk to the created processes. |
| 247 |
|
| 248 |
AnyEvent::Fork::Pool, to manage whole pools of processes. |
| 249 |
|
| 250 |
AUTHOR AND CONTACT INFORMATION |
| 251 |
Marc Lehmann <schmorp@schmorp.de> |
| 252 |
http://software.schmorp.de/pkg/AnyEvent-Fork-Remote |
| 253 |
|