From: John D. <du...@gm...> - 2007-11-21 16:56:34
|
Dear log4perl users, I am new to log4perl, I have search quite lot in FAQ and docs, but didnt't find the answer. How could I redirect the STDERR output of script executed through system() to logger? At the moment I use logging to file, but I would like to move it log4perl. Now: system "command 2>>errors.log"; I would like to redirect that error output to logger. Thanks a lot John. |
From: Kevin M. G. <cp...@go...> - 2007-11-21 19:01:42
|
John Dunbar wrote: > Now: system "command 2>>errors.log"; > I would like to redirect that error output to logger. Well, the safest and most direct way would be to replace/augment all the prints to STDERR (like "warn" and "die") inside your script with log4perl logger calls. Or you could pipe the output of your script to another script that reads STDIN and implements logging like this: command 2>&1 | perl -e 'use Log::Log4perl qw/:easy/; \ Log::Log4perl::easy_init($INFO); \ while (<STDIN>){INFO $_}' Or, if you wanted to get really crazy, if your perl is 5.8.0 or better, you can use PerlIO::via to grab STDERR and redirect it to your logger. This is completely untested, and I've never done it myself, but it would look something like this: --------------------------------------------- use PerlIO::via::Logger; use Log::Log4perl; Log::Log4perl->init(\<<EOL); log4perl.logger = DEBUG, FileAppndr1 log4perl.appender.FileAppndr1 = Log::Log4perl::Appender::File log4perl.appender.FileAppndr1.filename = stderr.log log4perl.appender.FileAppndr1.layout = Log::Log4perl::Layout::SimpleLayout EOL close STDERR; open(STDERR, ">:via(Logger)", '/dev/null'); warn "this is a warning, but stderr is being handled by the logger"; --------------------------------------------- package PerlIO::via::Logger; use Log::Log4perl qw/:easy/; sub PUSHED { my ($class,$mode,$fh) = @_; my $buf = ''; if ($mode ne 'w'){ #gah, can't use warn or die if they've closed STDERR! print STDOUT "this logger is only usable for writing, mode '$mode' not allowed"; exit(1); } return bless \$buf,$class; } sub WRITE { my ($obj,$buf,$fh) = @_; ERROR("message on stderr: $buf"); return length($buf); } sub FLUSH { my ($obj,$fh) = @_; #ignoring flush return 0; } 1; --------------------------------------- |
From: John D. <du...@gm...> - 2007-11-21 23:33:50
|
Kevin, thank you for comprehensive reply. > Well, the safest and most direct way would be to replace/augment all the > prints to STDERR (like "warn" and "die") inside your script with > log4perl logger calls. I would prefer this solution, but how can I the redirect whole output (or STDERR atleast) of the external command to die? I am almost perl beginner, sorry, if this question is too easy. > > Or you could pipe the output of your script to another script that reads > STDIN and implements logging like this: > > command 2>&1 | perl -e 'use Log::Log4perl qw/:easy/; \ > Log::Log4perl::easy_init($INFO); \ > while (<STDIN>){INFO $_}' Can I do this in perl script directly? use Log::Log4perl qw/:easy/; Log::Log4perl::easy_init($INFO); $pid = open(STDIN, "ls nonsense 2>/dev/null |"); while (<STDIN>){INFO $_}; Is there any way how to redirect STDOUT to INFO and STDERR to ERROR? If both is not possible, STDERROR to ERROR is more important. Thanks. -John |
From: Kevin M. G. <cp...@go...> - 2007-11-21 23:54:29
|
John Dunbar wrote: > Kevin, thank you for comprehensive reply. > >> Well, the safest and most direct way would be to replace/augment all the >> prints to STDERR (like "warn" and "die") inside your script with >> log4perl logger calls. > > I would prefer this solution, but how can I the redirect whole output > (or STDERR atleast) of the external command to die? > I am almost perl beginner, sorry, if this question is too easy. Sorry, I was assuming that this external command was perl code you had written. If it's some other command you don't have access to, then you can either wrap it in perl and use temp files to capture the output my $stdout = `command 2>/tmp/securetempfile`; or system("command 2>/tmp/stderr.out 1>/tmp/stdout.out"); (but use File::Temp to create the tempfile names, and keep in mind that the tempfiles can be accessed by anyone on that machine). >> Or you could pipe the output of your script to another script that reads >> STDIN and implements logging like this: >> >> command 2>&1 | perl -e 'use Log::Log4perl qw/:easy/; \ >> Log::Log4perl::easy_init($INFO); \ >> while (<STDIN>){INFO $_}' > > Can I do this in perl script directly? > > use Log::Log4perl qw/:easy/; > Log::Log4perl::easy_init($INFO); > $pid = open(STDIN, "ls nonsense 2>/dev/null |"); > while (<STDIN>){INFO $_}; See above with the backticks or the system call. > Is there any way how to redirect STDOUT to INFO and STDERR to ERROR? > If both is not possible, STDERROR to ERROR is more important. The tempfiles is a hacky but fairly reliable way to do it. See also IPC::Open3, where you can get the stdout and stderr of your child process on differen handles. |
From: John D. <du...@gm...> - 2007-11-22 00:20:36
|
ok, this seems to be the best: system("command 2>/tmp/stderr.out 1>/tmp/stdout.out"); is there any recommended way how to directly read these files with log4perl? I would like to append the output directly to output of logger. On Nov 22, 2007 12:54 AM, Kevin M. Goess <cp...@go...> wrote: > John Dunbar wrote: > > Kevin, thank you for comprehensive reply. > > > >> Well, the safest and most direct way would be to replace/augment all the > >> prints to STDERR (like "warn" and "die") inside your script with > >> log4perl logger calls. > > > > I would prefer this solution, but how can I the redirect whole output > > (or STDERR atleast) of the external command to die? > > I am almost perl beginner, sorry, if this question is too easy. > > Sorry, I was assuming that this external command was perl code you had > written. If it's some other command you don't have access to, then you > can either wrap it in perl and use temp files to capture the output > > my $stdout = `command 2>/tmp/securetempfile`; > > or > system("command 2>/tmp/stderr.out 1>/tmp/stdout.out"); > > (but use File::Temp to create the tempfile names, and keep in mind that > the tempfiles can be accessed by anyone on that machine). > > > >> Or you could pipe the output of your script to another script that reads > >> STDIN and implements logging like this: > >> > >> command 2>&1 | perl -e 'use Log::Log4perl qw/:easy/; \ > >> Log::Log4perl::easy_init($INFO); \ > >> while (<STDIN>){INFO $_}' > > > > Can I do this in perl script directly? > > > > use Log::Log4perl qw/:easy/; > > Log::Log4perl::easy_init($INFO); > > $pid = open(STDIN, "ls nonsense 2>/dev/null |"); > > while (<STDIN>){INFO $_}; > > See above with the backticks or the system call. > > > Is there any way how to redirect STDOUT to INFO and STDERR to ERROR? > > If both is not possible, STDERROR to ERROR is more important. > > The tempfiles is a hacky but fairly reliable way to do it. See also > IPC::Open3, where you can get the stdout and stderr of your child > process on differen handles. > |