Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Eval and system()

by camelman (Sexton)
on Sep 05, 2001 at 16:59 UTC ( #110275=perlquestion: print w/replies, xml ) Need Help??

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

I was reading through Advanced Perl Programming and read the chapter on Eval. I was trying to get a script to work with eval and system(), but I can't - probably because I really don't understand it.
eval { system("ls") };
Works fine. But consider this:
eval { system("fake_command) }; print "$@";
I get an error on the second example, but nothing prints for $@. The main reason I was looking at this (besides trying to learn something new) was because:
system("ls") or die $!;
runs but then produces an error about dying on that line. I'm probably way off the mark here, but I'm trying. Please don't flog me. TIA . . . Kevin

Replies are listed 'Best First'.
Re: Eval and system()
by dragonchild (Archbishop) on Sep 05, 2001 at 17:24 UTC
    It's not being caught in the compile phase. The program compiles just fine.

    You are working just fine with eval ... it's system (specifically on Unix) that's tripping you up. Try doing:

    eval { system "fake command" && print "Blah1\n" }; eval { system "fake command" || print "Blah2\n" }; eval { system "ls" && print "Blah3\n" }; eval { system "ls" || print "Blah4\n" };
    Unix commands are built off of the C libraries (for the most part). The standard C libraries, for reasons which will be left to your imagination, use '0' to indicate success and non-zero to indicate failure. Thus, the Unix commands tend to follow this (rather stupid) paradigm.

    In addition, system handles all the cleanup from failed commands. If you want to test $@, try

    eval { die "Hello!\n" }; print "Reason: $@\n"; eval { die "Hello!" }; print "Reason: $@\n";
    Try them both - they exhibit different behaviors of eval and die.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Vote paco for President!

      Not entirely true. For many programs if you get back $? of 256 (which is what a return code of 1 looks like), that is not necessarily an errror.

      Here is why. The return codes in the standard C libraries are an error code. 0 means, appropriately enough, no error. After that it is up to the author's imagination. In complex applications this generally means a standardized list of messages (kind of like the list enshrined in $!). In smaller applications people often use the convention that 1 is a minor issue that is not really an error and 2 is a fatal error.

      For instance try this:

      perl -e 'print system("ls no_such_file")'
      That gives back 256. It doesn't list anything, but none of its operations ran into trouble, and you might not have expected the file to be there. Now try that with a directory that you don't have permission to access. You will get back a more serious error - it cannot give you a real answer because you are not permitted to know that.
      • The standard C libraries, for reasons which will be left to your imagination, use '0' to indicate success and non-zero to indicate failure.
      I remember it this way: routine returns error number. If returns 0 => no errors. It makes sense for C, any kind of TRUE value means some error. But you can have only one kind of success, so OK == 0.

      If you looking at return value this way, it makes sense, right?

      pmas
      To make errors is human. But to make million errors per second, you need a computer.

      Thanks, monks. As always I learned quite a bit by asking a question here. I think I'll be going with:
      eval { system "fake command" && print "Blah1\n" };
      Initially I thought
      eval {system ("fake command")} or print "Blah1\n";
      was correct, but the first example works the way I want it to. Thanks . . . Kevin
      Sorry to insist, but: eval { system("fake_command) }; does not compile on my machine, due to a missing " and that's correct behaviour.

      Perhaps your Perl has a bug?

Re: Eval and system()
by monkfish (Pilgrim) on Sep 05, 2001 at 17:31 UTC
    First things first (OK this is actually the last thing first):

    system("ls") or die $!;

    This is dieing because system returns: "The return value is the exit status of the program as returned by the wait() call." In this case the system is returning 0 to perl on success. This is one of the problems with dependind on response code from things outside of perl. The results aren't always perl friendly.

    What you want is this:

    # Works $return = system("ls"); if ($return != 0) { die ($_); } #Dies $return = system("no_such_command"); if ($return != 0) { die ($_); }

    Now for the prior example:

    eval { system("fake_command) }; print "$@";

    I think you had a typo, but maybe you were trying to be really clever. Assuming it was a typo and you meant to include the close quote...

    $@ is "The Perl syntax error message from the last eval() command. If null, the last eval() parsed and executed correctly (although the operations you invoked may have failed in the normal fashion)."

    So the problem is that the perl code was fine, so there is nothing to report in $@. It is the system call that failed.

    Now, if you were being really clever and trying to show us bad perl code (the missing quote) and asking why eval didn't trap that, it is because the code won't compile as written and creates a syntax error rather than a trappable run time error.

    -monkfish (the fishy monk)

    Editted for clarity. 9/5/01

Re: Eval and system()
by busunsl (Vicar) on Sep 05, 2001 at 17:05 UTC
    You get an error on the second example, because the syntax is wrong (missing ") and this is checked in the compile phase.
    So your example doesn't run and thus no $@.

    The next example dies because system() returns the exit-code of the command it runs.
    Unix commands return 0 on success, which is false for Perl, hence it dies.

    Update: fixed typos

      Sorry about that! I meant:
      eval { system("fake_command") }; print $@;
      which still doesn't print $@, I guess because of it being caught in the compile phase. Thanks . . . Kevin
        It doesn't mean an error in eval when the command in system() fails.

        To check for that you can probably use:

        eval { system("false") and die "command 'false' went wrong!"}; print $@, "\n"

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://110275]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (6)
As of 2022-06-27 12:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My most frequent journeys are powered by:









    Results (88 votes). Check out past polls.

    Notices?