1 |
root |
1.2 |
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 |
|
|
|