BASH - Propagation of error codes

Hello.

I use bash functions which are in different script files.
Theses scripts function files are sourced when necessary.
As function does not easily return string value, Value are return using the echo function, and a return code is returned..

Now here my question :
In the main script I want to get the error code which is 0 if every things run correctly, otherwise it is different from 0.
As in my example "function2 return always 2, I expect an error code different from 0.
But I always get 0 ( success ).
I suppose because the last function in the pipe (not_important_function_b) always success and then set the return code to 0. Even if the first part of the pipe failed.

VERSION_VALUE=$( function2 "$MY_TEMPFILE" "a_string" "another_string" | not_important_function_b )  

How to catch the error from function2.

Any help is welcome.

Here the skeleton of my problem.

#!/bin/bash
# FILE : file2
#
function function_2 {not_important_function_c "$1"  "$2" "$3"
if [[ ! -z "$3" ]] ; thenCODE_ERR = 0
echo "GOOD_VALUE"
else
CODE_ERR = 1
fi
CODE_ERR = 2

retrun $CODE_ERR  # always return 2
}

#!/bin/bash
# FILE : file1
#
function function_1 {
#
    MY_TEMPFILE=$(mktemp)
    CODE_ERR_GLOB=$?  # never fail --> 0 success
#
    not_important_function_a "$1"  "$2"  > "$MY_TEMPFILE"
    CODE_ERR=$?  # never fail --> return 0 success
    (( CODE_ERR_GLOB += CODE_ERR ))
#
    VERSION_VALUE=$( function2 "$MY_TEMPFILE" "a_string" "another_string" | not_important_function_b )  
# function2 always fails -> return 2
# not_important_function_b never fails --> return 0 success
    echo "$?"
    CODE_ERR=$? # always 0 --> success but function2 fails
    echo "CODE_ERR : $CODE_ERR"
    (( CODE_ERR_GLOB += CODE_ERR ))
    echo "CODE_ERR_GLOB : $CODE_ERR_GLOB"
#
    rm -f $MY_TEMPFILE > /dev/null 2>&1
    CODE_ERR=$? # always 0 --> success but function2 fails
    (( CODE_ERR_GLOB += CODE_ERR ))
#
    if [[ $CODE_ERR_GLOB -eq 0  ]] ; then
        echo $VERSION_VALUE # echo a good value if no error nowhere
    fi
#
    return $CODE_ERR_GLOB always success but function2 fails
#
}
#!/bin/bash
#
#Main_program
#
source file1
source file 2
source file 3
#
MY_DATA=$(function_1 "param1" "param2" "param3")
ERR_CODE=$?     # always = 0 ! ! ! ! !
if [[  $ERR_CODE -ne 0 ]] ; thenecho "Error from function 1" # never print this
elseecho "Good data : $MY_DATA"
fi

1 Like

Hi,
In your code function_2, you have write retrun between return

Regards.

It is just a typo in this thread.

These script are just shown to explain the question.
The code by itself is not important.

In the coding line

VERSION_VALUE=$( function2 "$MY_TEMPFILE" "a_string" "another_string" | not_important_function_b )

If the last part of a pipe return no error and if a previous part of a pipe return one error, how to get the error code for the global result which must be considered as failing.

    echo "$?"
    CODE_ERR=$? # always 0 --> success but function2 fails

echo is executed successfully, so upon next check with $? it is 0 .
You probably want:

CODE_ERR=$?
echo $CODE_ERROR

hth

EDIT:
Thanked for the idea of making a function to print out a just created tempfile :b: :slight_smile:

It is just one more typo in this thread.

PS:
In your main script, maybe you could try something like:

if MY_DATA=$(function_1 "param1" "param2" "param3")
then echo "yay : $MY_DATA"
else err=$?
     echo "no : $err"
fi

hth

EDIT:
Your "typos" include beeing on the wrong line?
gee use the real one or care more about the example representing properly your question with working example... like... many of your code looks almost like incomplete csh, rather than bash.

My real program is working correctly.
These script are just shown to explain the question.
The code by itself is not important.

My real problem is the coding line

 VERSION_VALUE=$( function2 "$MY_TEMPFILE" "a_string" "another_string" | not_important_function_b )
RETURN_CODE=$?

If the last part of a pipe return no error and if a previous part of a pipe return one error (say 123)
1�) What is the value of $RETURN_CODE 0 or 123
2�) Is the return code set to 0 ( if not, I have a problem somewhere in my code)
how to get the error code (123) for the global result which must be considered as failing.

Thank you for helping

To my understanding it goes like:

If function2 FAILS, as in a code typo or floating number exception, then the pipe will be ignored and therefor the RETURN_CODE is the exception number of function2.
However, if function2 'ends' properly with an exit number, whatever comes out (or not) stdout will be passed to not_important_function_b which therfor will 'overwrite' the previous return value $? of function2, by its own value - as you report - 0.

hth

Ok,
In bash, you can propage error in pipe by setting pipefail:

$ false | true
$ echo $?
0
$ set -o pipefail
$ false | true
$ echo $?
1

Regards.

1 Like

Try the PIPESTATUS array:

$ true | false | true | false
$ echo ${PIPESTATUS[*]}
0 1 0 1

To save $PIPESTATUS :

$ true | false | true | false
$ foo=( ${PIPESTATUS[*]} )
$ echo ${keepme[*]}
0 1 0 1
1 Like

if your shell is not bash, then...

 with any other Bourne like shells

       You need to use a trick to pass the exit codes to the main
       shell.  You can do it using a pipe(2). Instead of running
       "cmd1", you run "cmd1; echo $?" and make sure $? makes it way
       to the shell.

       exec 3>&1
       eval `
         # now, inside the `...`, fd4 goes to the pipe
         # whose other end is read and passed to eval;
         # fd1 is the normal standard output preserved
         # the line before with exec 3>&1
         exec 4>&1 >&3 3>&-
         {
           cmd1 4>&-; echo "ec1=$?;" >&4
         } | {
           cmd2 4>&-; echo "ec2=$?;" >&4
         } | cmd3
         echo "ec3=$?;" >&4
       `
1 Like

I am running bash 4.2.53

---------- Post updated at 09:56 ---------- Previous update was at 09:39 ----------

Thank you every body for helping:b: