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

Hello,

I have just asked at Chatterbox and Corion tell me that it is not possible to change the return code when a perl script fails to compile. He said me about making a wrapper to perl script so it check the return code and return another.

I would like to have the reply and other ideas by written, so I'm posting here the same question.

I have next simple script (test.pl)
#!/usr/bin/perl -w use strict; print $c;
When it is interpreted by perl:
$ perl ~/test.pl Global symbol "$c" requires explicit package name (did you forget to d +eclare "my $c"?) at /home/javi/test.pl line 4. Execution of /home/javi/test.pl aborted due to compilation errors. $ echo $? 255
When it is executed through ssh:
$ ssh localhost perl ~/test.pl Global symbol "$c" requires explicit package name (did you forget to d +eclare "my $c"?) at /home/javi/test.pl line 4. Execution of /home/javi/test.pl aborted due to compilation errors. $ echo $? 255
Like says Corion, I can (on linux):
perl test.pl || if [ \$? -eq 255 ] ; then exit 254; fi

The origin of this question is trying to launch a real script (which I think (but I'm not sure) produces stdout and then it fail with 255 #1 ) with ansible:

https://github.com/ansible/ansible-modules-core/issues/5410

How would you fix this "ansible" issue ?

Any more elegant fix to distinguish between a real 255 ssh returned code and the 255 perl returned code?

ansible only look at ssh return code, and at ssh manpage:

 ssh exits with the exit status of the remote command or with 255 if an error occurred.

Thank you very much (and thank for Corion for the reply at Chatterbox)

Edited 2016/11/02
Created a pull request for ansible which basically add stderr to ansible message when ssh returns 255:
https://github.com/ansible/ansible/pull/18300

#1 updated 2016/11/07

I forgot to use strict on the original script, so it was producing output but returning 255. See:

#!/usr/bin/perl -w print "a\n"; print $c-d; $ perl test.pl Name "main::c" used only once: possible typo at test.pl line 4. a Can't use an undefined value as a symbol reference at test.pl line 4. $ echo $? 255

Replies are listed 'Best First'.
Re: 255: perl compilation error code and ssh cannot connect code
by Laurent_R (Canon) on Nov 02, 2016 at 07:20 UTC
    Can't you fix the program, rather than tampering its return code? It seems to me you should want to know if your program ends on an error.
      Hello,

      Of course I fixed my program, and now I make a pull request to ansible so that it display stderr and not "I can't connect to host"

      Thank you
Re: 255: perl compilation error code and ssh cannot connect code
by Anonymous Monk on Nov 02, 2016 at 01:33 UTC
    Sounds like some kind of wrapper script really would be best. Am on mobile right now so I can't test if the following works for compilation errors too, but END blocks should normally allow you to change the exit code, e.g. this at the top of your script: END { $? = 254 if $? == 255 } (again, warning, untested)

      Hi,

      Testing this shows that it appears to work, even for compile-time* errors:

      $ cat ex.pl #!/usr/bin/env perl use warnings; use strict; END { $? = 250 if $? == 255 } print $c; $ perl ex.pl ; echo $? Global symbol "$c" requires explicit package name (did you forget to d +eclare "my $c"?) at ex.pl line 7. Execution of ex.pl aborted due to compilation errors. 250

      Note this is documented in $?. However, this solution means you'd have to insert the END block at the top of every script that you run like this, so personally I like Corion's suggestion of a wrapper script better. Also, consider what kind of errors you are catching. Syntax errors are something that you can catch when you're developing the script, so I don't see how those could sneak in. Runtime errors, like you mention in the bug report accessing something that doesn't exist, are something you could catch and handle gracefully within the script, for example there's Try::Tiny.

      * Update: Actually I think this may be inaccurate, although it seems to catch many syntax errors and such, there might be cases where the END block isn't executed; if I get around to it I'll test more later.

      Hope this helps,
      -- Hauke D

        Maybe good idea only change the result if it is executed via ssh:
        #!/usr/bin/env perl use warnings; use strict; END { $?=254 if defined $ENV{SSH_CONNECTION} and $? eq 255 } print $c;
        A big thank for your reply !

        Hi i5513,

        But I did not realized about END code should go before the end of the script

        The idea is Perl needs to see the END block before it hits the error, otherwise it doesn't get queued for execution. So it's best to put the END block as early as possible. See also BEGIN, UNITCHECK, CHECK, INIT and END.

        Hope this helps,
        -- Hauke D

Re: 255: perl compilation error code and ssh cannot connect code
by stevieb (Canon) on Nov 01, 2016 at 23:14 UTC

    Can you please post the first 5-10 lines of /home/javi/test.pl script?

    This looks like you have strict enabled (yay!), but haven't properly declared your $c variable.

    I haven't had a chance to look through CB, but code here would be helpful anyway

      Hello,

      It is a simple wrong written script. I only use it as example for the question.

      At the real world, I had an 800 lines script (which i surely will publish at github when it is ready) which was working though ansible until I had a error on it ( I think it was a fatal error after it wrote some lines on stdout). Then I debugged the problem to find the reason, that is why I'm asking this question.

      Thank you

      PD: If I find time I will try to search an example which write on stdout and then exit with 255 code because an error

        So does your real script compile? What's the output of:

        perl -c /home/user/script.pl

        ...where the path is the path to your real 800 line script.

        What you're looking for is: script.pl syntax OK. If it isn't, please post the output. If it's overly long, post the first five lines, and the last five lines (separated by whitespace so we can tell where any gap is).