我正在研究Perl中的机器人(基于POE),到目前为止一直很好,但我无法弄清楚如何添加!js
或!perl
命令来评估各自编码并返回要打印到通道中的一行输出。我发现App::EvalServer但我不知道如何使用它。
感谢您的帮助!
答案 0 :(得分:3)
App::EvalServer
模块附带一个二进制文件作为standalone application运行。你没有把它放在你的程序中,而是自己运行它。它打开一个端口,您可以将其作为json字符串传递给它。这对我来说听起来也不是一个好主意。
您可能希望查看另一个名为Safe的模块。我建议您在完成任何操作之前先阅读完整的文档以及Opcode(在文档中链接)的文档。 如果您评估任意代码,您可能会遭受严重损害!永远不会忘记这一点。
<强>更新强>
以下是如何从print
ed代码中捕获say
或eval
的输出的示例。您可以将open
与变量一起使用,以使print
输出始终转到该变量。如果之后切换回来,则可以使用var中捕获的输出。这称为内存中文件。
use strict; use warnings;
use feature 'say';
use Safe;
# Put our STDOUT into a variable
my $printBuffer;
open(my $buffer, '>', \$printBuffer);
# Everything we say and print will go into $printBuffer until we change it back
my $stdout = select($buffer);
# Create a new Safe
my $compartment = new Safe;
$compartment->permit(qw(print)); # for testing
# This is where the external code comes in:
my $external_code = qq~print "Hello World!\n"~;
# Execute the code
my $ret = $compartment->reval($external_code, 1);
# Go back to STDOUT
select($stdout);
printf "The return value of the reval is: %d\n", $ret;
say "The reval's output is:";
say $printBuffer;
# Now you can do whatever you want with your output
$printBuffer =~ s/World/Earth/;
say "After I change it:";
say $printBuffer;
免责声明:使用此代码需要您自担风险!
更新2 :在聊天中进行了长时间的讨论后,我们提出了这个问题。它实现了一种超时,以便在reval
长时间停止执行时停止执行,例如因为无限循环。
#!/usr/bin/perl
use warnings;
use strict;
use Safe;
use Benchmark qw(:hireswallclock);
my ($t0, $t1); # Benchmark
my $timedOut = 0;
my $userError = 0;
my $printBuffer;
open (my $buffer, '>', \$printBuffer);
my $stdout = select($buffer);
my $cpmt = new Safe;
$cpmt->permit_only(qw(:default :base_io sleep));
eval
{
local $SIG{'ALRM'} = sub { $timedOut = 1; die "alarm\n"};
$t0 = Benchmark->new;
alarm 2;
$cpmt->reval('print "bla\n"; die "In the user-code!";');
# $cpmt->reval('print "bla\n"; sleep 50;');
alarm 0;
$t1 = Benchmark->new;
if ($@)
{
$userError = "The user-code died! $@\n";
}
};
select($stdout);
if ($timedOut)
{
print "Timeout!\n";
my $td = timediff($t1, $t0);
print timestr($td), "\n";
print $printBuffer;
}
else
{
print "There was no timeout...\n";
if ($userError)
{
print "There was an error with your code!\n";
print $userError;
print "But here's your output anyway:\n";
print $printBuffer;
}
else
{
print $printBuffer;
}
}
答案 1 :(得分:2)
看看perl eval(),你可以传递变量/字符串,它会像它的perl代码那样评估它。同样在javascript中,还有一个eval()函数,其功能类似。
然而,不要在perl或javascript中评估任意代码,除非您可以在完全封闭的环境中运行它(即便如此,它仍然是一个坏主意)。很多人花了很多时间preventing just this from happening。所以你就是这样做的,但你真的不想这样做。