Isn't this one of those currently unsolvable problems? I've been trying to separately but synchronously handle
STDOUT and STDERR for months now. The closest I've gotten is
(big program follows)
#!/opt/local/bin/perl -w
######################################################################
+#############
#Script to run jobs that are to be logged on "cron output page." Norm
+ally used by calls from the cron daemon,
#it may be used interactively to capture output for posting on web by
+report.pl.
######################################################################
+#############
#Edited JWC 7/26/06 with the use of special output-handling functions
+for cleaner output.
######################################################################
+#############
#Edited JWC 8/19/06 to know which user is running it (before just assu
+med it was m1jwc03)
######################################################################
+#############
#Edited JWC 9/20/06 to compress log file (strip blank lines with sed)
#This is because after playing with the handlers for the different kin
+ds of output, I still saw
#blank lines. It's useful to compare the start and finish times of cr
+on jobs (finish time is
#assumed to be the last mod time of the log file) and periodically run
+ning sed on the files
#in the directory would ruin that. Thus, the sedding of the files by
+this program.
######################################################################
+#############
use IPC::Run qw( run );
use File::Basename;
use strict;
#$ENV{'IPCRUNDEBUG'} = basic;
#need two arguments: script to run and mailing list (comma-separated m
+1 ids)
$#ARGV == 1 || die "Error: Need exactly two arguments!\n";
#( $base, $dir, $ext ) = fileparse( $ARGV[0], '\..*' );
my @fp = fileparse( $ARGV[0], '\..*' );
my $base=$fp[0];
my $dir=$fp[1];
#Do some machinations to create a unique overall log file
my @now = localtime;
#months returned by localtime() are zero-indexed.
#got to pad the zeroes for the time/date elements
my $mo = sprintf( "%02d", $now[4] + 1 );
my $d = sprintf( "%02d", $now[3] );
my $y = $now[5] + 1900;
my $h = sprintf( "%02d", $now[2] );
my $mi = sprintf( "%02d", $now[1] );
#changed this line to reflect hosting it locally JWC 7/20/06
my $workdir = "/fst/prod1/lib/cron/logs";
#$workdir="/fst/prod1/lib/cron/logs";
my $me = `whoami`;
chomp($me);
my $logfile = "$workdir/$base-$y$mo$d.$h$mi.$me.log";
open( LOG, ">$logfile" ) || die "Error: Could not open $logfile: $!\n
+";
$|++;
my $oldfh = select(LOG) || die "Error: Could not select LOG: $!\n";
#got rid of \n prefix to get rid of extra space --
#RegExp in report.pl does not need this to be on a line by itself. JWC
+ 7/26/06
my $endrun = "*-*-end_run-*-*";
$|++;
print "*-*-begin_run-*-*\n";
( my $distlist = $ARGV[1] ) =~ s/,/ /g;
print "*-*-on_error $distlist-*-*\n";
chdir("$dir");
my @cmd = $ARGV[0];
#$SIG{CHLD} = sub {
#removed 9/12/06 always seemed to occur at the end and told me nothing
+.
#print "NOTE: in sig{CHLD}\n";
# if (waitpid($pid, 0) > 0){sleep(1);};
#};
#die turned to warn, had $& in there when I should have had $? as the
+return value 6/7/6 JWC
{
run(\@cmd, '>pty>', \&stdhandler,
'2>', \&errhandler )
or warn("Error executing child? Child returned $?.
Child returned ".($? >> 8)." and died from signal number ".($? & 127)
+." Core dump status: ".($? & 128)." dollar bang is ".$!."\n");
}
print $endrun;
#have to put in this cos we may have something to say after the log is
+ closed now JWC 9/20/06
select($oldfh);
close(LOG);
#Gets rid of newlines in log file added JWC 9/29/06
my $stat=system("sed -i '/^\$/d' $logfile");
($stat) && print "sed returned $stat; $?; $!; $^E";
sub stdhandler {
#moved this to before anything else JWC 9/15/06
chomp $_[0];
#for HTML compatibility JWC 8/4/06
#oops this messes up my HTML input in the scripts (like divider span
+s and such) JWC 8/7/06
#$_[0] =~ s/</</g;
#$_[0] =~ s/>/>/g;
#used to be $_[0] =~ s/\^M//g; JWC 8/24/06
$_[0] =~ s/\r//g;
#added space before and after the > signs. Also, Matlab tends to cr
+eate them in pairs.8/24/06 JWC
$_[0] =~ s/^\s*(\s*>>\s*)+\s*$//g;
&trim;
#added this 8/1/06 to further eliminate blank lines JWC
#Moved this last in the order 8/24/06 JWC
$_[0] =~ s/^$//g;
$_[0] && print "$_[0]\n";# : print "empty string\n";
}
sub errhandler {
chomp $_[0];
#for HTML compatibility JWC 8/4/06
$_[0] =~ s/</</g;
$_[0] =~ s/>/>/g;
&trim;
$_[0] && print "<span id='stderr'>$_[0]</span>\n";# : print "empty s
+tring\n";
}
sub trim {
@_ = $_ if not @_ and defined wantarray;
@_ = @_ if defined wantarray;
for (@_ ? @_ : $_) { s/^\s+//, s/\s+$// }
return wantarray ? @_ : $_[0] if defined wantarray;
}
It's obviously quite rough and for normal programs (Perl scripts that run FAME, SAS, etc), it's close enough, but if you run a program like
#% is the modulo operator so it's switching back and forth between eve
+n and odd numbers
$|++;
$\="\n";
for (my $i=0; $i < 100; $i++){
if ($i % 2){ print STDERR $i; }
else {print $i;}
}
I get blocks of like 10 even numbers, then 12 odd numbers, then 15 even, then 8 odd, etc.
My apologies if this is not helpful and/or I have misunderstood your problem. Good luck.
Good luck.
_________________________________________________________________________________
I like computer programming because it's like Legos for the mind.