Perl CGI脚本如何与Web服务器上的守护进程通信?

时间:2009-11-14 02:42:12

标签: perl daemon server-side

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

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

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

是否有可用的Perl模块可以使我的消息传递更简单 没有我担心沟通是如何发生的?我有纯文本的远程命令,可能希望将数据恢复为XML / JSON。

3 个答案:

答案 0 :(得分:1)

听起来你想做类似以下的事情:

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

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

答案 1 :(得分:1)

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

1)如果需要实时响应以立即发回给用户(这里似乎是这种情况),那么使用套接字与守护进程通信是可行的方法。共享内存,管道和诸如此类的东西还有其他选项,但是使用套接字为您提供了一个简单的可扩展性路径,用于是否需要将前端Web服务器和后端守护程序分解到不同的计算机上。

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

答案 2 :(得分: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);