English 中文(简体)
How can a Perl CGI script communicate with a daemon on the webserver?
原标题:

I am building a Web interface to monitor an embedded system. I have built a Perl script which runs remote commands and gathers output from that system. Now what I need is a Web interface which makes calls to this script (executes remotes command) and displays data on the web page.

First of all, I need to make my script as a daemon process which can accept requests from the Web Server. I can choose any server-side technology as long as it can communicate with this Perl script. To keep it simple, I can choose Perl/CGI which can talk to this daemon Perl script.

What is the best way to communicate with this daemon script? I haven t decided on how the communication needs to be—sockets or anything else.

Are there Perl modules already available which can make my message passing simpler without me worrying about how the communication takes place? I have remote commands in plain text and might want to have the data back in XML/JSON.

最佳回答

You did not explain why the existing perl script can t be run directly from the Perl/CGI script ? This seems the easiest path to me, as it does not involve creating another communication channel:

client ⇒ apache ⇒ your CGIzed existing script ⇒ embedded system

as opposed to:

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

I assume the reason is that you expect the CGI script to run multiple times simultaneously, and the embedded system is not able to handle multiple connections.

But even in this case, having a daemon for the only purpose of serialization seems overkill. You can use a lock in the CGI script, to protect the critical communication code, as in:

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

Note that the "crital code" part could either embed your existing script, or execute it.

If, despite all this, you still want to separate the CGI from the command daemon, here are templates for the client and server parts of socket-based communication. First, the client, which is part of the CGI:

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

And this is the main daemon loop:

package MyServer;
use base Net::Server;
sub process_request {
    my $self = shift;
    while (<STDIN>) {
        chomp;
        print "This is my answer to the command  $_ .
";
    }
}
MyServer->run(port => 160);
问题回答

Sounds like you want to do something like the following:

Your CGI web daemon would look something like this: (Not Tested)

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
}

And your script that calls the CGI web daemon would compose a URL to call the daemon in this sort of fashion: (again, Not Tested)

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

In the past, when I ve needed to do something like this, I ve generally handled the communication in one of two ways:

1) If the response is needed in real-time to send back to the user immediately (as appears to be the case here), then using sockets to talk to the daemon is the way to go. There are other options with shared memory, pipes, and whatnot, but using sockets gives you an easy scalability path for if/when you need to break the front-end web server and back-end daemon out onto separate machines.

2) If the response isn t time-critical, I ve tended to shove the incoming commands onto a queue stored in a database table and then had the daemon periodically poll the queue for new tasks. This tends to be a bit easier to implement and scales up even better then the socket-based option, provided you can deal with the limitation of all communication going through the database.





相关问题
Why does my chdir to a filehandle not work in Perl?

When I try a "chdir" with a filehandle as argument, "chdir" returns 0 and a pwd returns still the same directory. Should that be so? I tried this, because in the documentation to chdir I found: "...

How do I use GetOptions to get the default argument?

I ve read the doc for GetOptions but I can t seem to find what I need... (maybe I am blind) What I want to do is to parse command line like this myperlscript.pl -mode [sth] [inputfile] I can use ...

Object-Oriented Perl constructor syntax and named parameters

I m a little confused about what is going on in Perl constructors. I found these two examples perldoc perlbot. package Foo; #In Perl, the constructor is just a subroutine called new. sub new { #I ...

Where can I find object-oriented Perl tutorials? [closed]

A Google search yields a number of results - but which ones are the best? The Perl site appears to contain two - perlboot and perltoot. I m reading these now, but what else is out there? Note: I ve ...

热门标签