2009-11-14 5 views
1

Je construis une interface Web pour surveiller un système embarqué. J'ai construit un script Perl qui exécute des commandes à distance et rassemble les résultats de ce système. Maintenant, j'ai besoin d'une interface Web qui appelle ce script (exécute la commande des télécommandes) et affiche les données sur la page Web. Tout d'abord, je dois faire mon script en tant que processus démon qui peut accepter les demandes du serveur Web. Je peux choisir n'importe quelle technologie côté serveur tant qu'elle peut communiquer avec ce script Perl. Pour rester simple, je peux choisir Perl/CGI qui peut parler à ce démon script Perl.Comment un script CGI Perl peut-il communiquer avec un démon sur le serveur Web?

Quelle est la meilleure façon de communiquer avec ce script daemon? Je n'ai pas décidé comment la communication doit être — sockets ou toute autre chose.

Existe-t-il déjà des modules Perl qui peuvent rendre mon message plus simple sans que je me soucie de la façon dont la communication a lieu? J'ai des commandes à distance en texte brut et je souhaite récupérer les données en XML/JSON.

Répondre

1

Vous n'avez pas expliqué pourquoi le script perl existant ne peut pas être exécuté directement à partir du script Perl/CGI? Cela semble le chemin le plus facile pour moi, car il ne comporte pas la création d'un autre canal de communication:

client ⇒ apache ⇒ your CGIzed existing script ⇒ embedded system 

par opposition à:

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

Je suppose que la raison est que vous attendez le script CGI pour exécuter plusieurs simultanément et le système embarqué n'est pas capable de gérer plusieurs connexions.

Mais même dans ce cas, avoir un démon dans le seul but de la sérialisation semble trop.Vous pouvez utiliser un verrou dans le script CGI, pour protéger le code de communication critique, comme dans:

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

Notez que la partie « code crital » pourrait soit intégrer votre script existant, ou l'exécuter.

Si, malgré tout, vous voulez toujours séparer le CGI du démon de commande, voici des modèles pour les parties client et serveur de la communication basée sur socket. Tout d'abord, le client, qui fait partie du 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; 

Et ceci est la boucle démon principal:

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); 
+0

Merci pour votre réponse. Je regarderai. La raison pour laquelle je veux qu'ils soient séparés est que pour chaque système embarqué j'ai une seule connexion que je veux multiplexer pour chacun des utilisateurs qui envoient une requête pour surveiller/exécuter des commandes à distance via la page web. Et j'ai plusieurs tels systèmes embarqués et les utilisateurs peuvent surveiller un ou plusieurs en même temps sur des pages différentes. Aussi je veux avoir la flexibilité de fournir la même fonctionnalité via une application basée sur la console à l'avenir. – mtanish

+0

Oh, donc la connexion avec le système embarqué est de rester debout tout le temps? Je comprends maintenant. Je pense que la solution de socket pour laquelle j'ai fourni des modèles est appropriée. De plus, l'utilisation du paquet Net :: Server vous donne un serveur de commandes sur lequel vous pouvez facilement obtenir un accès à la console par telnet. – Jerome

1

On dirait que vous voulez faire quelque chose comme ce qui suit:

Votre démon Web CGI ressemblerait à quelque chose comme ceci: (Non testé)

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 
} 

Et votre script qui appelle le démon Web de CGI serait composer une URL pour appeler le démon dans ce genre de mode: (encore une fois, non testé)

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

dans le passé, quand j'ai besoin de faire quelque chose comme ça, je suis généralement manié la communication de l'une des deux manières suivantes:

1) Si la réponse est nécessaire en temps réel pour renvoyer à l'utilisateur immédiatement (comme cela semble être le cas ici), l'utilisation de sockets pour parler au démon est le marche à suivre. Il existe d'autres options avec de la mémoire partagée, des tuyaux, etc., mais l'utilisation de sockets vous donne un chemin d'évolutivité facile pour si/quand vous avez besoin de séparer le serveur web frontal et le démon back-end sur des machines séparées. 2) Si la réponse n'est pas urgente, j'ai eu tendance à placer les commandes entrantes dans une file d'attente stockée dans une table de base de données, puis j'ai demandé au démon d'interroger périodiquement la file d'attente de nouvelles tâches. Cela a tendance à être un peu plus facile à implémenter et à faire évoluer encore mieux que l'option basée sur le socket, à condition de pouvoir gérer la limitation de toutes les communications passant par la base de données.

+0

réponse est pas le temps super valeurs critiques mais mises à jour de permet de dire des compteurs ou cpu stats besoins être affiché sur une base continue. Socket semble être une option viable. Merci – mtanish

Questions connexes