Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

"Exception" handling and more...

by r.joseph (Hermit)
on Nov 26, 2001 at 13:56 UTC ( [id://127513] : perlquestion . print w/replies, xml ) Need Help??

r.joseph has asked for the wisdom of the Perl Monks concerning the following question:

Hey all! It's been a while since I last really worked with Perl - with my school completely moving to Java, and with my classes taking up nearly 100% of my time, I haven't had a chance to dive into a big 'ol project lately - well, now I going to.

Basically, I am fiddling around with Filesys::SmbClientParser (sorry, I forgot the PM syntax for linking to modules - any help?), which parses the output of the smbclient binary. My problem is that sometimes I get error messages that are of no importance, but that are sent to STDERR - I want to be able to catch these error messages before they get to the screen and send them somewhere more useful (a log, maybe).

As I have been working with Java a lot lately, I am hooked on Exception Handling in Java, and it seems like this would be a similar situation - however, I have never worked with any of Perl's error handling (is there any?) capabilites, so I am lost with what to do here.

Thanks for the help!

r. j o s e p h
"Violence is a last resort of the incompetent" - Salvor Hardin, Foundation by Issac Asimov

Replies are listed 'Best First'.
Re: "Exception" handling and more...
by rob_au (Abbot) on Nov 26, 2001 at 14:44 UTC
Re: "Exception" handling and more...
by MZSanford (Curate) on Nov 26, 2001 at 14:45 UTC
    If you don't need to know which parts are from stderr, and which are from stdout, i would suggest appending 2>&1 to your command. This will cause the unix shell to rediect them both so you can read them.

    On the other hand, if they have to be seperate, i would suggest :
    1. using pipe() twice
    2. fork()'ing off a child.
    3. Using open() in the child to reset STDOUT and STDERR to the writing ends of the pipes.
    4. using exec() in the child to start the command
    5. let the parent (from the fork()) read the other ends of the pipes, and process them seperatly.

    ... just a thought.
    i had a memory leak once, and it ruined my favorite shirt.
Re: "Exception" handling and more...
by gildir (Pilgrim) on Nov 26, 2001 at 15:17 UTC
    Perl does not have such a complex exception system like Java has.

    In Perl, exceptions can be generated by using die(). These 'die exceptions' can be caught by enclosing them to eval{}. It works much like Java's throw/catch system.

    But nothing enforces any standard nor strong convention on how object thrown by die() has to look like. Most implementations (and perl core too) dies with plain string. Only way to evaluate such an exception is pattern match on $@ after eval. This looks quite cumbersome to me. But there is some light at the end of a tunnel, for example Exception module from CPAN.

    But ... even if this worked just like it works in Java, vast majority of modules does not use this mechanism. It is not Perl programmer's 'common sense' to use exceptions. Many of intermediate Perl coders even doesn't know that any way to use exceptions exists in perl.

    Back to your original question: forget the exceptions if you want to use a module. Look at STDERR redirection as the other repries indicated. Check the error codes. Alternatively, you may encloce module call to eval { call_here() };, but this will not stop module writing to STDERR, it only catches die() conditions.

    Another option could be __WARN__ handler. If the module you are using uses warn() to print to STDERR, you may use $SIG{__WARN__} = \&logging_routine; to catch the warnings.

Re: "Exception" handling and more...
by hotshot (Prior) on Nov 26, 2001 at 14:48 UTC
    you can catch STDERR from your script or system commands in two ways:
    my $errorCode = system(SYSCOMMAND/SCRIPT);
    that will give you the error code of the syscommand/script.
    my $errorMessage = `SYSCOMMAND/SCRIPT`; # back ticks
    will give you the error message maybe checking $! will help you too