Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Greetings.

I am trying to discover how to use App::Cronjob, and in the process I've stumbled across a problem with the dependency Getopt::Long::Descriptive. I thought that calling the run method of App::Cronjob with no arguments, would allow me to follow how App::Cronjob was working, so that I could make some documentation to give to another person. Instead of G::L::D generating a usage message, I am getting problems with symbolic references (perl 5.10.0 on Debian/unstable). I don't understand the process of generating the usage message. In particular:

sub text { shift->(1) }
If I turn off strict in G::L::D just before this statement, I get an undeclared subroutine ($main::1).

But if someone could comment on the usage message process for G::L::D, that would be wonderful. Thanks.

Replies are listed 'Best First'.
Re: Usage message, and App::Cronjob
by almut (Canon) on Jun 11, 2009 at 21:14 UTC
    I don't understand the process of generating the usage message...

    The usage message is being generated in G::L::D::describe_options(), line 362:

    $usage->die unless GetOptions(\%return, grep { length } @specs);

    when the call to GetOptions() has determined that there's something wrong with the arguments (like being called without an argument, in your case).

    The $usage object is a blessed subroutine reference, constructed somewhat further up like this (simplified):

    my $usage = bless sub { my ($as_string) = @_; ... return $buffer if $as_string; } => "Getopt::Long::Descriptive::Usage";

    The object's die() method is then calling the text() method that you mentioned

    sub die { my $self = shift; my $arg = shift || {}; die( join( "", grep { defined } $arg->{pre_text}, $self->text, $arg->{post_text +}, ) ); }

    passing it $self, which is the function reference blessed into G::L::D::Usage. In other words, the shift->(1) in

    sub text { shift->(1) }

    is a function call which is being passed 1 as argument. That argument sets the $as_string flag, which controls whether the message is being returned as a string or printed to STDERR.

    Does that help?

    That said, I'm not exactly sure why you're expecting that calling App::Cronjob with no arguments, would allow you to follow how App::Cronjob was working...

      When I write programs, I normally start with simple things, such as running the program with no arguments. I am guessing you looked at App::Cronjob? The manpage is not of much help, there are no /examples, and the only test doesn't show anything useful. It was not obvious to me, how the heck one uses this module. I have learned a lot since I posted this, and I am currently trying to figure out why it can't find sendmail, when exim has provided sendmail.

      It may be that all of my problems were due to insufficient documentation. That I had these problems may be due to insufficient error trapping in the modules. Had all of the code been more "obvious", I may not have run into this. I am just trying to find a better way to solve these problems should they occur in the future with other CPAN modules. At this point, I have not enough experience with how these modules actually work to know if they are doing what I would like them to do or not.

      What seems to be needed, is that the entire perl program needed is:

      #!/usr/bin/perl use App::Cronjob; App::Cronjob::run();

      Is this supposed to be obvious? Looking at Cronjob.pm, I thought I needed to provide a hash to run(), to provide the values. That triggered the symbolic reference problem. Allowing symbolic references shifted the problem to $main::1() not found. Putting a bunch of command line stuff (such as --subject="No Subject") into @ARGV, I don't think worked (does @ARGV lose its magic, if the location of the list changes?) Pushing my arguments onto @ARGV at least let me get past this symbolic reference problem. Fine, I've now run into this thing about sendmail. I suspect I will soon have some documentation as to how to use this module, which looks to be a good solution to a problem in mu LUG. So, I am slowly getting to find how to use this module on my own. That isn't the problem I am asking about. How the heck does one find this kind of problem, and how do you solve it in the future? I looked at the bug reports and test matrix for G::L::D, and seen nothing which would indicate there was a problem. When I write usage messages, they are pretty simple. I have never run across code remotely like what G::L::D was doing. I never would have expected code like that to behave how I seen it behave. Maybe this is just a problem for people who run similar code inside emacs using perldb? Does it depend only on the original @ARGV (or things pushed onto @ARGV)? Can we unshift things onto @ARGV instead? Am I making sense? Thanks.

        Is this supposed to be obvious?

        It is obvious that App::Cronjob is not ready, best to seek alternate solutions.

Re: Usage message, and App::Cronjob
by rjbs (Pilgrim) on Jun 12, 2009 at 18:41 UTC
    Hi, I wrote App::Cronjob. I am happy to help anyone who asks, just drop me an email or RT ticket. I only saw this report because a friend pointed me this way.

    In general, App::Cronjob is not meant to be used directly. That's why it's not documented for such use -- it needs to be refactored, etc.

    Instead, you are meant to use the installed "cronjob" command. We use this command *extensively* at work. Example use:

    0 * * * * /opt/pobox/bin/cronjob -E -c "/usr/sbin/logadm"

    I do not general frequent the monastery, so please consider following up via email or RT ticket.

    rjbs