############################################################ #!/usr/bin/perl -w # this script printf to stdout and stderr. It prints random # characters and does not flush the output of stdout. stderr # is autoflushed by default. # uncomment the line about autoflush STDOUT to see how that # changes the behavior. Also, you can uncomment the sleep # line to watch the script in slow motion. use warnings; use strict; use IO::Handle; #autoflush STDOUT 1; for (1..100){ my $str = ''; for(1..80){ $str .= ('A'..'Z','a'..'z',0..9)[rand 62]; } if(int rand 2){ # 50:50 chance print STDOUT "StdOut:$str"; } else { print STDERR "StdErr:$str"; } # sleep 1; } ############################################################ #!/usr/bin/perl -w # this script runs the previous script and catches both # child's stdout and stderr. It prints progress information # as it goes. It also prints the data it gets to the # corresponding file. use strict; use warnings; #use diagnostics; use IPC::Open3; use IO::Select; use Symbol; my $cmd = "./test.pl"; open(ERRLOG, ">error.log") or die "Can't open error log! $!"; open(OUTPUT, ">output.log") or die "Can't open output log! $!"; my ($infh,$outfh,$errfh); $errfh = gensym(); # if you uncomment this line, $errfh will # never be initialized for you and you # will get a warning in the next print # line. my $pid; eval{ $pid = open3($infh, $outfh, $errfh, $cmd); }; die $@ if $@; print "IN: $infh OUT: $outfh ERR: $errfh\n"; print "PID was $pid\n"; # now our child is running, happily printing to # its stdout and stderr (our $outfh and $errfh). my $sel = new IO::Select; # create a select object $sel->add($outfh,$errfh); # and add the fhs # $sel->can_read will block until there is data available # on one or more fhs while(my @ready = $sel->can_read) { # now we have a list of all fhs that we can read from foreach my $fh (@ready) { # loop through them my $line; # read up to 4096 bytes from this fh. # if there is less than 4096 bytes, we'll only get # those available bytes and won't block. If there # is more than 4096 bytes, we'll only read 4096 and # wait for the next iteration through the loop to # read the rest. my $len = sysread $fh, $line, 4096; if(not defined $len){ # There was an error reading die "Error from child: $!\n"; } elsif ($len == 0){ # Finished reading from this FH because we read # 0 bytes. Remove this handle from $sel. # we will exit the loop once we remove all file # handles ($outfh and $errfh). $sel->remove($fh); next; } else { # we read data alright print "Read $len bytes from $fh\n"; if($fh == $outfh) { print OUTPUT $line; } elsif($fh == $errfh) { print ERRLOG $line; } else { die "Shouldn't be here\n"; } } } } # now that the child closed both its handles, I assume it # exited. # ps will show you the child. print `ps`; # go ahead and reap it waitpid $pid, 0; # wait for it to die # not it's no more print `ps`; close(ERRLOG) or die "Can't close filehandle! $!"; close(OUTPUT) or die "Can't close filehandle! $!";