After reading through the various previous replies and the linked material I put together the following two test applications. The CGI app is heavily based on the sample code in merlyn's LinuxMag column Watching long processes through CGI (pointed to by McDarren++), with amendments so that it works under Windows (but no longer under *nix, although making both work in this "framework" ought be trivial). In the real application the CGI app would manage the monitored app by writing to a second file.
The managing app:
#!Perl -w
use strict;
use CGI::Pretty qw(:standard :cgi-lib);
use CGI::Carp qw(fatalsToBrowser); # Remove for production code
use File::Cache;
$CGI::DISABLE_UPLOADS = 1; # Disable uploads
$CGI::POST_MAX = 10240; # Maximum number of bytes per post
$| = 1; # Unbuffered output
if (param('Spawn')) {
# setup monitoring page then spawn the monitored process
my $session = get_session_id();
my $cache = get_cache_handle();
$cache->set($session, "wait ..."); # no data yet
Delete_all();
# parent redirects browser to monitor session
param('session', $session);
print redirect (self_url());
close STDOUT;
# Rest of this block alters in *nix context to spawn monitored pro
+cess
use Win32::Process;
my $job;
Win32::Process::Create (
$job,
'c:/Perl/bin/perl.exe', "perl.exe spawned.pl $session",
0,
NORMAL_PRIORITY_CLASS | DETACHED_PROCESS,
'.'
);
exit 0; # all done
} elsif (my $session = param('session')) {
# display monitored data
my $cache = get_cache_handle();
my $data = $cache->get($session);
if (! $data) { # something is wrong
showError ("Cache data not available");
exit 0;
}
my $headStr = $data eq 'Completed' ? '' : "<meta http-equiv=refres
+h content=5>";
print header();
print start_html (-title => "Spawn Results", -head => [$headStr]);
print h1("Spawn Results");
print pre(escapeHTML($data));
print end_html;
} else {
# display spawn form
print header(), start_html("Spawn"), h1("Spawn");
print start_form();
print submit('Spawn', 'spawn');
my %params = Vars ();
for my $param (keys %params) {
print br ("$param -> $params{$param}");
}
print end_form(), end_html();
}
exit 0;
sub showError {
print header(), start_html("SpawnError"), h1("Spawn Error");
print p (shift);
my %params = Vars ();
for my $param (keys %params) {
print br ("$param -> $params{$param}");
}
print end_html();
}
sub get_cache_handle {
File::Cache->new
({
namespace => 'Spawn',
username => 'nobody',
default_expires_in => '30 minutes',
auto_purge_interval => '4 hours',
});
}
sub get_session_id {
require Digest::MD5;
Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().$$));
}
The monitored app:
#!Perl -w
use strict;
use File::Cache;
my $session = shift;
my $cache = get_cache_handle();
$cache->set($session, "wibble ..."); # no data yet
my $end = time () + 20;
my $count = 0;
while (time () < $end) {
$cache->set ($session, "Count: $count\n");
++$count;
sleep (1);
}
$cache->set ($session, "Completed");
exit 0; # all done
sub get_cache_handle {
File::Cache->new
({
namespace => 'Spawn',
username => 'nobody',
default_expires_in => '30 minutes',
auto_purge_interval => '4 hours',
});
}
The code was tested using a local Apache server and seems to provide exactly the types of interaction I am looking for.
Are there any glaring oversights?
DWIM is Perl's answer to Gödel
|