Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching exception of a shell command in Perl 6

Tags:

raku

I had to run a shell program exiting with an error from Perl 6, so I've decided to test how it works. I've made a bash script producing an error to run it from a Perl 6 program:

$ cat prog.sh 
echo "error" >&2
exit 1

Here is how I call it from Perl 6:

put "start";
  try {
    shell "./prog.sh";
  }
put "end";

The output shows that the program exited after running the shell command.

start
error
The spawned command './prog.sh' exited unsuccessfully (exit code: 1)
  in block <unit> at b.p6 line 2

If I add a CATCH block

put "start";
  try {
    shell "./prog.sh";
    CATCH { default {} }
  }
put "end";

everything is OK, and the program works to the last line:

start
error
end

So my question: why is it necessary to add the CATCH block, while try by itself cannot tackle the error?

like image 493
Eugene Barsky Avatar asked Oct 01 '18 19:10

Eugene Barsky


People also ask

How do I catch an exception in Perl?

Catch the exception using evalIf we wrap a piece of code in an eval block, the eval will capture any exception that might happen within that block, and it will assign the error message to the $@ variable of Perl. The simple way to do this looks like this: (please note, there is a ; after the eval block.)

How do you call a shell command in a Perl script?

We use the backticks ( `` ) syntax when we want to capture the output of the shell command. We provide the command between the backticks. If we don't want to capture the output of the shell command, we use the system function, as shown below. The system function will just display the output.

How do I run a Perl command in terminal?

From Perl HowTo, the most common ways to execute external commands from Perl are: my $files = `ls -la` — captures the output of the command in $files. system "touch ~/foo" — if you don't want to capture the command's output. exec "vim ~/foo" — if you don't want to return to the script after executing the command.

How do I run an exec in Perl?

exec - Perldoc Browser. The exec function executes a system command and never returns; use system instead of exec if you want it to return. It fails and returns false only if the command does not exist and it is executed directly instead of via your system's command shell (see below).


1 Answers

shell doesn't throw the Exception until the sink.

The try block with only the shell in it fully executes without an exception being thrown, returning the last value in the block, which then gets sunk outside the context of the try, which then throws the Exception.

You can see this with:

put "start";
  try {
    shell "./prog.sh";
    'something';
  }
put "end";

Now the shell gets sunk inside the try, which gets caught by the implicit CATCH of the try. The try block returns the last value in the block, the 'something', which then gets safely sunk outside the try.

You can also force the sink to happen inside the try:

put "start";
try {
   sink shell "./prog.sh"
}
put "end";

Your added CATCH block is just preventing the try block from returning the return value from the shell.

You can re-arrange them and see that this still blows up:

put "start";
try {
    CATCH { default {} }
    shell "./prog.sh";
}
put "end";

The best, most clear way to handle this IMHO would be to check the return from the shell yourself rather than letting it sink and throw the Exception:

put "start";
if shell "./prog.sh" {
    say 'ok'
}
else {
    say 'failed'
}
put "end";
like image 133
Curt Tilmes Avatar answered Oct 12 '22 12:10

Curt Tilmes