why error code 1 returned by loading .bash_profile in Mac
Solution 1:
Note that what happens when using return
outside a function without having source
d the script (e.g. return
ing from .bash_profile
) is undocumented in man bash
.
The difference is in how the return code of a script or function is recorded internally in bash
. If you return
a value, that value is assigned the return code of the calling code, e.g. the function call you return from, or the source
command. As there is no such caller when returning from .bash_profile
during shell initialization, that value is simply discarded. What you're accessing as $?
is the return code of the preceding statement.
Using Apple's bash-86.1 as reference:
If you source
a script, its contents are parsed and executed, until a return
statement is encountered. Its return value is recorded separately, and it's the responsibility of the caller (execute_command_internal
in bash-3.2/execute_cmd.c
) to assign its value to the variable holding the last exit code: last_command_exit_value
.
If it's called as a startup script, it is loaded via a call to maybe_execute_file
in the run_startup_files
function in bash/shell.c
. It's not regular command execution: While the contents of the file are executed properly, including the final return
, nobody cares about the actual value you're returning. It is simply discarded.
So, what behavior are you seeing here? Essentially the same as if you'd called return
without argument: Like return
simply returned the return code of the command preceding it, which, in your case, is the failed test.
How to get the desired behavior? Since you can't exit
from .bash_profile
without quitting the shell, you need to make sure the command immediately preceding it produces the desired return code, in this case:
test -f $HOME/.debug && export profile_bash_profile='.bash_profile' || { true; return; }
Solution 2:
I have figured the following out by trial and error. Maybe a BASH guru can explain some more.
-
.bashrc
contents:test -f $HOME/existent_file || return 4
After opening a new terminal:
$ echo $? 0
-
.bashrc
contents:test -f $HOME/non_existent_file || return 4
After opening a new terminal:
$ echo $? 1
-
.bashrc
contents:function foo () { return 4 } foo;
After opening a new terminal:
$ echo $? 4
-
.bashrc
contents:return 4
After opening a new terminal:
$ echo $? 0
-
With the same
.bashrc
as above:$ source ~/.bashrc $ echo $? 4
-
These commands run directly from a terminal:
$ test -f $HOME/existent_file || return 4 $ echo $? 0 $ test -f $HOME/non_existent_file || return 4 bash: return: can only `return' from a function or sourced script $ echo $? 1
So, return
only works from functions and sourced files. I don't know how a user's ~/.bashrc
is read but apparently it is not sourced.