我正在使用 Perl(基于 POE)开发一个机器人,到目前为止一切都很好,但我不知道如何添加一个!js
or!perl
命令来评估相应的代码并返回一行输出以打印到通道中. 我找到了App::EvalServer但我不知道如何使用它。
谢谢你的帮助!
我正在使用 Perl(基于 POE)开发一个机器人,到目前为止一切都很好,但我不知道如何添加一个!js
or!perl
命令来评估相应的代码并返回一行输出以打印到通道中. 我找到了App::EvalServer但我不知道如何使用它。
谢谢你的帮助!
该App::EvalServer
模块附带一个二进制文件,可作为独立应用程序运行。你不要把它放在你的程序中,而是自己运行它。它打开一个端口,您可以在其中将代码作为 json 字符串传递。这对我来说也不是一个好主意。
您可能想查看另一个名为Safe的模块。我建议您在对此进行任何操作之前通读完整的文档以及Opcode的文档(链接在文档中)。如果您评估任意代码,您可能会造成严重损害!永远别忘了。
更新:
下面是一个示例,说明如何捕获 ed 代码的输出print
或say
来自eval
ed 代码的输出。您可以使用open
with a variable 使print
ed 输出始终转到该变量。如果你之后切换回来,你可以在你的 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;
}
}
看一下perl eval(),您可以将变量/字符串传递给它,它会像 perl 代码一样评估它。同样在 javascript 中,还有一个eval()函数执行类似的操作。
但是,不要在 perl 或 javascript 中评估任意代码,除非您可以在完全封闭的环境中运行它(即使那样,这仍然是一个坏主意)。很多人花费大量时间来防止这种情况发生。所以你就是这样做的,但你根本不想这样做。