Search code examples
bashvariablesexit-code

bash functions, local variables, and exit codes


In a bash function, I'm trying to capture the output of a command along with it's exit code. Generally, my form is

some_function() {
local rv=$(some_other_function)
local code=$?
echo "$rv"
return $code
}

but I notice that whenever I use 'local', then $? is ALWAYS 0. Like it's capturing the result of the assignment, not the called function. If I don't use 'local', then it works as expected:

$ foo() { local rv=$(false); echo "code is $?"; }
$ foo
code is 0
$ foo() { rv=$(false); echo "code is $?"; }
$ foo
code is 1

Can someone explain this to me? Obviously something fundamental here I just don't understand.


Solution

  • Can someone explain this to me?

    In simple words most of the time $? has the exit status of last command executed. The last command is local. The return status of local is zero - it successfully made rv a local variable. Stupid example:

    echo $(false) $(true) $(false)
    ^^^^ - this is the last command executed
    # $? here has exit status of **echo**
    

    Separate the assignment from local:

    local rv code
    # Assignment is not a "command", in the sense it preserves exit status.
    # The last command executed in assignment is the one inside `$(...)`.
    rv=$(some_other_function)
    code=$?  # will have the exit status of expression executed inside $(...)
    

    Check your scripts with http://shellcheck.net . Shellcheck warns about such mistakes.