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: [email protected]