failed command in pipeline not triggering "catch" command

100 Views Asked by At

I am trying to set up a small block of code so that if any piece of it fails, it will trigger another line of code to be run. So like:

cmd1 || cmd2

However, the first segment has a pipe in it, so:

cmd1 | cmd2 || cmd3

However, if cmd1 fails, cmd3 does not run.

If have tried the following, with the same result each time:

( cmd1 | cmd2 ) || cmd3
{ cmd1 | cmd2 } || { cmd3 }

For completeness, this is the specific block of code I am working with:

{
        {
            pkexec apt -y install (package-file-name) | zenity --progress --pulsate --auto-close --no-cancel --text="installing (package-name) . . ." 

        } && {
            notify-send "(package-name) has been installed"
        }
} || {
        zenity --error --text="Error code: $?"
}

So far, it runs as if the "catch" statement (if you want to call it that) does not even exist. Also, the first part of it specifically, before the pipe, is the part that if it fails it won't throw an error. I have not had any issues with the second part of the pipe so I am unsure if it will exhibit the same behavior.

Thanks in advance!

3

There are 3 best solutions below

0
On BEST ANSWER

In bash, you can set pipefail. eg:

$ cat a.sh
#!/bin/bash

false | true || echo executed 1
set -o pipefail
false | true || echo executed 2
$ ./a.sh
executed 2
0
On
( cmd1 | cmd2 ; exit ${PIPESTATUS[0]}) || cmd3

This should work for you if you have no problems with running those commands in subshell i.e. ().

0
On

You can use process substitution to make the exit status of zenity irrelevant.

if pkexec apt -y install (package-file-name) > >(
     zenity --progress --pulsate --auto-close --no-cancel --text="installing (package-name) . . ."
   ); then 
    notify-send "(package-name) has been installed"
else
    zenity --error --text="Error code: $?"
fi

Alternatively, you can use an explicit named pipe to avoid the need for any non-standard shell extensions.

mkfifo p
zenity --progress --pulsate --auto-close --no-cancel --text="installing (package-name) . . ." < p &

if pkexec apt -y install package-file-name > p; then
    notify-send "(package-name) has been installed"
else
    zenity --error --text="Error code: $?"
fi