1

我正在构建一个 Web 界面来监控嵌入式系统。我已经构建了一个 Perl 脚本,它运行远程命令并从该系统收集输出。现在我需要的是一个 Web 界面,它调用这个脚本(执行远程命令)并在网页上显示数据。

首先,我需要将我的脚本作为一个可以接受来自 Web 服务器的请求的守护进程。我可以选择任何服务器端技术,只要它可以与这个 Perl 脚本通信。为了简单起见,我可以选择可以与这个守护进程 Perl 脚本对话的 Perl/CGI。

与此守护程序脚本进行通信的最佳方式是什么?我还没有决定通信需要如何——套接字或其他任何东西。

是否已经有 Perl 模块可以使我的消息传递更简单,而我不必担心通信是如何发生的?我有纯文本的远程命令,可能希望以 XML/JSON 格式返回数据。

4

3 回答 3

1

听起来你想做如下的事情:

您的 CGI Web 守护程序看起来像这样:(未测试)

use CGI;
my $cgi = new CGI;
if ($cgi->param('action') eq "MyFirstCommand") {
    # perform your actions for this command and output a response to STDOUT
}
elsif ($cgi->param('action') eq "MySecondCommand") {
    # perform your actions for this command and output a response to STDOUT
}

并且您调用 CGI Web 守护程序的脚本将组成一个 URL 以这种方式调用守护程序:(再次,未测试)

use LWP::Simple;
my $URL = 'http://hostname:port/cgi-bin/daemon-script.cgi?action=MyFirstCommand';
my $http_response = LWP::Simple::get($URL);
# analyze the response for success or failure
于 2009-11-15T02:59:40.123 回答
1

过去,当我需要做这样的事情时,我通常以两种方式之一处理通信:

1)如果需要实时响应以立即发送回用户(就像这里的情况一样),那么使用套接字与守护进程对话是可行的方法。共享内存、管道等还有其他选项,但使用套接字为您提供了一个简单的可扩展性路径,以便您在需要将前端 Web 服务器和后端守护程序拆分到单独的机器上时使用。

2)如果响应不是时间关键的,我倾向于将传入的命令推送到存储在数据库表中的队列中,然后让守护程序定期轮询队列以获取新任务。与基于套接字的选项相比,这往往更容易实现并且可以更好地扩展,前提是您可以处理通过数据库的所有通信的限制。

于 2009-11-15T11:35:58.083 回答
1

你没有解释为什么现有的 perl 脚本不能直接从 Perl/CGI 脚本运行?这对我来说似乎是最简单的途径,因为它不涉及创建另一个沟通渠道:

client ⇒ apache ⇒ your CGIzed existing script ⇒ embedded system

相对于:

client ⇒ apache ⇒ new CGI script ⇒ existing script ⇒ embedded system

我假设原因是您希望 CGI 脚本同时运行多次,而嵌入式系统无法处理多个连接。

但即使在这种情况下,为了序列化的唯一目的而拥有一个守护进程似乎有点过分了。您可以在 CGI 脚本中使用锁来保护关键的通信代码,如下所示:

open(my $lock, ">", $lockfilename);
flock($lock, LOCK_EX);
... critical code...
flock($lock, LOCK_UN);

请注意,“关键代码”部分可以嵌入您现有的脚本,也可以执行它。

如果尽管如此,您仍想将 CGI 与命令守护程序分开,这里是基于套接字通信的客户端和服务器部分的模板。首先是客户端,它是 CGI 的一部分:

use IO::Socket::INET;
$sock = IO::Socket::INET->new('localhost:9000');
print $sock "Comand\n";
$result = <$sock>;
... do something with the result ...
$sock->close;

这是主要的守护程序循环:

package MyServer;
use base Net::Server;
sub process_request {
    my $self = shift;
    while (<STDIN>) {
        chomp;
        print "This is my answer to the command '$_'.\r\n";
    }
}
MyServer->run(port => 160);
于 2009-11-15T11:49:21.813 回答