On Tue 17 Mar 2009, Tom Spencer wrote: > So far so good, it adds the information I've got to the database > quite nicely. But the one more thing I really need is all the STDERR > that was generated while processing the request. Recipe 6.10 > provides a method for outputting STDERR to a different file but I'd > like to grab it and put it into my database.
First thing, you have to specify your understanding of "all the STDERR" in more detail. Is it 1) the warn and die output 2) all that perl writes to STDERR 3) something that XS modules or rather libraries used by XS modules write to filedescriptor 2 4) the stuff that apache logs to the virtual hosts errorlog Here are some ideas how to solve these problems: 1) set $SIG{__WARN__} and $SIG{__DIE__} or implement &CORE::GLOBAL::warn and &CORE::GLOBAL::die 2) reopen STDERR to a memory filehandle, eg: perl -Mstrict -e ' # list our open fds to see what is going on system "ls -l /proc/$$/fd"; # save fd2 as SAVEERR open SAVEERR, ">&STDERR" or die "Cannot dup: $!"; close STDERR; # make sure that nobody else can open fd2 by chance open my $acquirefd2, ">", "/dev/null" or die "acquire: $!"; # check it system "ls -l /proc/$$/fd"; my $err; # open memory filehandle open STDERR, ">", \$err or die "open: $!"; # this output must not differ from the previous system "ls -l /proc/$$/fd"; # some printout to STDERR and a warning # nothing appears on the terminal print STDERR "print to STDERR\n"; warn "warning"; # print the error output to STDOUT surrounded by >><< print ">>$err<<\n"; close STDERR; system "ls -l /proc/$$/fd"; # release fd2 close $acquirefd2; # redirect STDERR to the original fd2 open STDERR, ">&SAVEERR" or die "restore: $!"; close SAVEERR; # check it system "ls -l /proc/$$/fd"; # these will appear on the terminal print STDERR "print to STDERR\n"; warn "warning"; ' This is what I see (a bit commented): total 0 lrwx------ 1 r2 users 64 2009-03-18 12:32 0 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 1 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 12 -> socket:[12916] lrwx------ 1 r2 users 64 2009-03-18 12:32 13 -> socket:[12917] # fd2 points to my terminal lrwx------ 1 r2 users 64 2009-03-18 12:32 2 -> /dev/pts/9 lr-x------ 1 r2 users 64 2009-03-18 12:32 3 -> pipe:[10303] l-wx------ 1 r2 users 64 2009-03-18 12:32 4 -> pipe:[10303] lr-x------ 1 r2 users 64 2009-03-18 12:32 5 -> pipe:[31529] lrwx------ 1 r2 users 64 2009-03-18 12:32 7 -> socket:[12899] total 0 lrwx------ 1 r2 users 64 2009-03-18 12:32 0 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 1 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 12 -> socket:[12916] lrwx------ 1 r2 users 64 2009-03-18 12:32 13 -> socket:[12917] # now it points to /dev/null lrwx------ 1 r2 users 64 2009-03-18 12:32 2 -> /dev/null lr-x------ 1 r2 users 64 2009-03-18 12:32 3 -> pipe:[10303] l-wx------ 1 r2 users 64 2009-03-18 12:32 4 -> pipe:[10303] # but fd5 (SAVEERR) points to my terminal lr-x------ 1 r2 users 64 2009-03-18 12:32 5 -> /dev/pts/9 lr-x------ 1 r2 users 64 2009-03-18 12:32 6 -> pipe:[31546] lrwx------ 1 r2 users 64 2009-03-18 12:32 7 -> socket:[12899] total 0 lrwx------ 1 r2 users 64 2009-03-18 12:32 0 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 1 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 12 -> socket:[12916] lrwx------ 1 r2 users 64 2009-03-18 12:32 13 -> socket:[12917] lrwx------ 1 r2 users 64 2009-03-18 12:32 2 -> /dev/null lr-x------ 1 r2 users 64 2009-03-18 12:32 3 -> pipe:[10303] l-wx------ 1 r2 users 64 2009-03-18 12:32 4 -> pipe:[10303] lr-x------ 1 r2 users 64 2009-03-18 12:32 5 -> /dev/pts/9 lr-x------ 1 r2 users 64 2009-03-18 12:32 6 -> pipe:[31554] lrwx------ 1 r2 users 64 2009-03-18 12:32 7 -> socket:[12899] # the framed output >>print to STDERR warning at -e line 19. << total 0 lrwx------ 1 r2 users 64 2009-03-18 12:32 0 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 1 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 12 -> socket:[12916] lrwx------ 1 r2 users 64 2009-03-18 12:32 13 -> socket:[12917] # still the same: fd2 points to /dev/null, fd5 to my terminal lrwx------ 1 r2 users 64 2009-03-18 12:32 2 -> /dev/null lr-x------ 1 r2 users 64 2009-03-18 12:32 3 -> pipe:[10303] l-wx------ 1 r2 users 64 2009-03-18 12:32 4 -> pipe:[10303] lr-x------ 1 r2 users 64 2009-03-18 12:32 5 -> /dev/pts/9 lr-x------ 1 r2 users 64 2009-03-18 12:32 6 -> pipe:[31561] lrwx------ 1 r2 users 64 2009-03-18 12:32 7 -> socket:[12899] total 0 lrwx------ 1 r2 users 64 2009-03-18 12:32 0 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 1 -> /dev/pts/9 lrwx------ 1 r2 users 64 2009-03-18 12:32 12 -> socket:[12916] lrwx------ 1 r2 users 64 2009-03-18 12:32 13 -> socket:[12917] # here it is reverted, fd2 is the terminal, fd5 is something else # (due to the ls command) lrwx------ 1 r2 users 64 2009-03-18 12:32 2 -> /dev/pts/9 lr-x------ 1 r2 users 64 2009-03-18 12:32 3 -> pipe:[10303] l-wx------ 1 r2 users 64 2009-03-18 12:32 4 -> pipe:[10303] lr-x------ 1 r2 users 64 2009-03-18 12:32 5 -> pipe:[31568] lrwx------ 1 r2 users 64 2009-03-18 12:32 7 -> socket:[12899] # this output is now unframed print to STDERR warning at -e line 33. 3) save file descriptor 2 to another one (via dup), close it, reopen it on a temporary file, read that file in your log handler and restore the original filedescriptor 2 (for each request). (similar to 2)) 4) requires a bit of C-hacking. Apache provides an error-log hook that cannot be used by now from perl. error_log declared in ./include/http_log.h implemented in ./server/log.c type is VOID void error_log(const char *file, int line, int level, apr_status_t status, const server_rec *s, const request_rec *r, apr_pool_t *pool, const char *errstr) Torsten -- Need professional mod_perl support? Just hire me: torsten.foert...@gmx.net