Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Perl exception - multiple statement

by pradeepbstays (Initiate)
on Jul 20, 2009 at 16:16 UTC ( [id://781670] : perlquestion . print w/replies, xml ) Need Help??

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

Hi, I have a perl which executes multiple UNIX command (using the system f +unction). Incase of any error in any one of the statements , I need to stop the +execution there and capture the actual error thrown. I tried using eval with $@ , but it didnt work. This is what i tried: --------------------------------------------------------- eval { system("cp xyz.dat abc.dat"); system("cp xyz.dat2 abc.dat2"); }; if ($?) { print "Error occured :".$@; print "\n"; } ~ --------------------------------------------------------- And the output is: % perl temp.perl cp: cannot access xyz.dat cp: cannot access xyz.dat2 Error occured : --------------------------------------------------------- I want the control to come out when the first copy failed.And also wan +t to cupture and log the actual error message. Can some one tell how to achive this. Thank you, Pradeep

Replies are listed 'Best First'.
Re: Perl exception - multiple statement
by kennethk (Abbot) on Jul 20, 2009 at 16:30 UTC
    In order to escape from the eval block, you need to tell Perl something unexpected has occurred. This usually done with die, where you should check $? after each system command, a la:

    eval { system("cp xyz.dat abc.dat"); die "$?\n" if ($?); system("cp xyz.dat2 abc.dat2"); die "$?\n" if ($?); }; if ($@) { print "Error occured: $@\n"; }

    Please note the difference in reliable scoping between $? and $@ - as noted in Error Indicators.

    Update: As JavaFan notes, this does not capture the actual error messages, only the error codes returned from system (as per your OP). If you want to handle the actual error messages, you'll need to capture STDERR, as per 781684.

      Note that just "solution" doesn't give you the actual error message. Just information about the exit value, the signal that terminated the child, and whether core was dumped.
Re: Perl exception - multiple statement
by ikegami (Patriarch) on Jul 20, 2009 at 16:55 UTC
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Perl exception - multiple statement
by spazm (Monk) on Jul 20, 2009 at 16:32 UTC
    1. when using eval, you want to check the status of $@ ( and not $? as you have in your snippet )
    2. system calls don't throw errors that you can check with eval.
    3. system returns 0 on success.
    4. $? and $!, which one is which, I tend to have to check the docs.


      We can define our own system call that will throw an error (die) on failure.

      Quick example:

      sub my_system { system($_[0]) || die "$_[0] failed : $!"; } eval { my_system( "cp xyz.dat abc.dat" ); my_system("cp xyz.dat2 abc.dat2"); } if ($@) { print "Error occured : $@\n" }
Re: Perl exception - multiple statement
by JavaFan (Canon) on Jul 20, 2009 at 16:35 UTC
    You can use backticks to capture STDOUT. Since you are using cp, which doesn't output to STDOUT, you can merge STDERR into STDOUT, and capture errors that way. Then use && to string the commands together. Something like (untested):
    my $err = `(cp xyz.dat abc.dat && cp xyz.dat2 abc.dat2) 2>&1`; if ($?) { print "Error message: $err"; print "Exit status: ", $? >> 8; }
Re: Perl exception - multiple statement
by davorg (Chancellor) on Jul 20, 2009 at 16:28 UTC