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

Hi Monks

I wrote this little sub, it runs a system command that executes a external package called htmldoc. I did not install the software to see when the software is not running proparly, if it will return anything in $@

When I execute the sub it spools to the screen
'htmldoc' is not recognised as an internal or external command, but $@ is empty. I need the sub routine to return a 1 if it was successful or 0 if there was an error

Please Help

sub html_to_pdf { my($pdffile,$htmlfile)=@_; $command = "htmldoc --webpage -f \"$pdffile\" \"$htmlfile\""; print $command."\n"; eval{system("$command");}; print "\$\@:$@\n"; if($@) { print "html to pdf Failed->\n$@\n"; return 0; } #if($@) else { return 1; } #else for if($@) } #sub html_to_pdf

Replies are listed 'Best First'.
Re: Another eval $@ question
by ikegami (Patriarch) on Oct 13, 2006 at 05:40 UTC

    system("$command"); will never throw an exception for eval {} to catch. On error, system returns an error code, not an exception. Please refer to the documentation. (By the way, $? is set to system's error code.)

    Please please please use a list for system's arguments whenever possible. It is MUCH safer since it doesn't involve the shell. (What if $pdffile contained a "?)

    my @command = ('htmldoc', '--webpage', '-f', $pdffile, $htmlfile); my $rv = system(@command); die("Unable to execute htmldoc: $!\n") if $rv == -1; die("htmldoc was unable to complete the request (Exit code = $&)\n") if $rv; ... success! ...

    Update: Expanded code to show error handling.

      system("$command"); will never thrown an exception for eval {} to catch.
      Yes and no:
      $ perl -we'$SIG{CHLD} = sub { die "whoa there" }; eval { system("true" +) }; print "!$@!"' !whoa there at -e line 1. !
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Another eval $@ question
by bobf (Monsignor) on Oct 13, 2006 at 05:33 UTC

    Other monks will likely have better ideas, but here are my thoughts.

    • I can't tell from your post if printing to the screen is acceptable or not. If not, then you may have to redirect STDERR (perlfaq8, specifically "Why can't I get the output of a command with system()?" and "How can I capture STDERR from an external command?", or you can Super Search).
    • It looks like your eval will trap a fatal error when the calling the system command, but that doesn't appear to be what you want. You can probably eliminate it since the system call will likely succeed (you appear to want to test the result of the command, not the result of the system call).
    • If you want to trap the output of the command, you should be using backticks or qx instead (see perlop).
    • If you want to capture the return value of the command, system is correct. Do you know what the return value is if the command succeeds? If so, you can check for that in your if/else and return accordingly.

    I hope this gives you a start. The bottom line is that I don't think eval is what you want here, and it's hard to give you more specific advice until you tell us how you will tell the difference between success and failure for the command (output vs exit value).

    Update: added a link to perlfaq8

      You are correct in saying -> (you appear to want to test the result of the command, not the result of the system call).

      I do currently spool the STDERR and STDOUT to a file but I'm not to sure how to put this in a variable for only selected cases

      Here is how I spool the STDERR & STDOUT to File. I'll also look at If you want to trap the output of the command, you should be using backticks or qx instead (see perlop).

      open (STDOUT, "> $system_folder\\system.log") or die "Can't redirect s +tdout: $!"; open (STDERR, ">&STDOUT") or die "Can't dup stdout: $!";

      Thank you

Re: Another eval $@ question
by blazar (Canon) on Oct 13, 2006 at 10:12 UTC
    sub html_to_pdf { my($pdffile,$htmlfile)=@_; $command = "htmldoc --webpage -f \"$pdffile\" \"$htmlfile\"";

    (General recommendation) please (do a favour to yourself and)

    use strict; use warnings;

    As a side note you can use alternate delimiters:

    my $command = qq|htmldoc --webpage -f "$pdffile" "$htmlfile"|;

    is quite more readable IMHO. But then I would recommend you to use the list form of system which has the advantage of avoiding passing through the shell, which in turn you don't seem to need.

    print $command."\n"; eval{system("$command");};

    You plainly don't need eval. The actual call may fail, but the system command may well succeed. It is its return value, along with $?, that you have to check.