1

I would like to use a Perl variable from my script in a Log::Log4perl config file. I read the documentation and found that I can use a subroutine, but I would like to do it a little bit simpler, if possible.

I want to set the filename for my appender:

log4perl.appender.av_std_LOGFILE.filename="whateverfilename.log"

But doing this this way, it is a fixed value.

I have the filename in a variable within my script and would like to use this at runtime:

log4perl.appender.av_std_LOGFILE.filename=\
 sub { return &av_getLogfileName(); }

Where this is the subroutine:

sub av_getLogfileName
{
    return $av_std_LOGFILE;
}

This works, but I would like to avoid the sub inside my script since the return value is very simple.

The documentation says:

Each value starting with the string sub {... is interpreted as Perl code to be executed at the time the application parses the configuration...

So I tried something like this, but it did not work:

log4perl.appender.av_std_LOGFILE.filename=\
    sub { print "$av_std_LOGFILE"; }

Is there a way to get result of the variable without the sub inside my script?

ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
averlon
  • 325
  • 3
  • 14
  • You said `$av_std_LOGFILE` is set in a script a couple times and a module a couple times. Which is it? – ThisSuitIsBlackNot May 12 '16 at 15:44
  • Also, you shouldn't call subroutines with `&` unless you know what that does. `return &av_getLogfileName();` should be `return av_getLogfileName();` (or better yet, `return av_get_logfile_name();`, mixing snake case and camel case is really hard to read and snake case is generally preferred in Perl). – ThisSuitIsBlackNot May 12 '16 at 15:51

1 Answers1

5

print returns 1 on success, so

sub { print "$av_std_LOGFILE"; }

returns 1, not the value of $av_std_LOGFILE. You also have to fully qualify variable names in hooks, which means you'll have to make $av_std_LOGFILE a package global.

Change your hook to:

sub { return $main::av_std_LOGFILE; } # double quotes are unnecessary

and set $av_std_LOGFILE in your script like this (before calling Log::Log4perl::init):

our $av_std_LOGFILE = '/path/to/logfile';

Generally, you should avoid global variables, so I would prefer using a subroutine.

ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
  • thanks; I get error messages: Can't open (Datei oder Verzeichnis nicht gefunden) at /home/fx42252/perl5/lib/perl5/Log/Log4perl/Appender/File.pm line 124. at /home/fx42252/perl5/lib/perl5/Log/Log4perl/Appender/File.pm line 129. – averlon May 13 '16 at 05:34
  • Either you're not setting `$av_std_LOGFILE` in package `main`, or you're setting it after you call `Log::Log4perl::init`. If you're setting the variable inside a module, you need to use the module's package name, e.g. if your module code is `package Foo::Bar; our $av_std_LOGFILE = '/foo';` then your hook would be `sub { return $Foo::Bar::av_std_LOGFILE; }` – ThisSuitIsBlackNot May 13 '16 at 06:05
  • lets skip the expression "module". I am using perl up to now to replace a bash script. So there is not realy a structure like package, module, ..... What I understood so far is, by using perl that way, it is all "main::". Not sure. Anyhow: You can be sure the variable is set at the time init is used. – averlon May 13 '16 at 06:45
  • our $av_std_LOGFILE='test.log'; $av_std_DEBUG && say "debug \$av_std_LOGFILE: $av_std_LOGFILE"; Log::Log4perl::Config->utf8( 1 ); Log::Log4perl::init( "av_log4perl.conf" ); my $logger = get_logger();$logger->error("Blah"); that is all of the script- just for testing. – averlon May 13 '16 at 06:47
  • see my edits of the original question which now shows the whole script. – averlon May 13 '16 at 06:56
  • @averlon Your code works for me when I copy and paste it verbatim and run it from the directory containing `av_log4perl.conf`. Try passing the full path to the config file in the call to `Log::Log4perl::init`. Also, please don't change your question to a completely different question after people have spent time giving answers. Feel free to post a new question if you can't figure this out, but make sure your problem is reproducible. As I said, your code works fine for me. – ThisSuitIsBlackNot May 13 '16 at 14:20
  • I tried to copy @ThisSuitIsBlackNot in at the beginning of my comment but failed. Sorry I am a little bit confused with the usage of stackoverflow. I did not change the question. But since someone questioned that I have set the variable I have posted the whole script to show it is done! Now it's gone. – averlon May 14 '16 at 08:38
  • I cant get the user name with @ included in the comments even where the help tells me how - but this does not work for me; it still does not work for me, even when I changed the conf-file name to full path. Unfortunately the comment field here is to small to post the error message. – averlon May 14 '16 at 09:09
  • O.K.; I found the error; I had an additional line im my config-file but commented out; This line broke the structure. Now it works. Thanks to @ThisSuitIsBlackNot – averlon May 14 '16 at 09:27