Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Whenever I open a bash terminal, the error code 1 is returned:

Last login: Tue Jan 15 16:19:53 on ttys000
spam@moss:~ $ echo $?
1

I found this is caused by last line of code in my .bash_profile:

test -f $HOME/.debug && export profile_bash_profile='.bash_profile' || return 0

If I remove this line, then the error code 0 is returned. I don't understand how this line could cause any problem, because I can source .bash_profile with the error code 0:

spam@moss:~ $ source .bash_profile
spam@moss:~ $ echo $?
0

Update:

Does anyone one know how Mac load ~/.bash_profile? I doubt Mac sources it when a login shell is launched. It seems the return command doesn't run as expected - when I put return 5 as the last line of ~/.bash_profile and launch a login shell, it does not return error code 5 (and I am sure ~/.bash_profile is the last script loaded).

share|improve this question
    
Mac OS X’s bash loads its dot files the same way as on other platforms (keeping in mind the OS X Terminal always starts a login shell in a new tab or window). The only explanation that comes to my mind is that there is indeed another file loaded after .bash__profile, one in which the exported profile_bash_profile is used and triggers an error (hence exit code 1 – possibly because the var is not set to path, but only to a file name?). –  kopischke Jan 16 '13 at 20:55
    
what are the possible files that could be loaded after .bash_profile? I only have ~/.bashrc and don't have ~/.profile, so I don't think I have any other files loaded after .bash_profile. –  RNA Jan 16 '13 at 21:52
    
That’s difficult to say without access to your system config. Check .bash_profile for anything that sources other files (like, say, .bashrc), then anything included by homebrew if you use that. –  kopischke Jan 17 '13 at 6:19

2 Answers 2

Note that what happens when using return outside a function without having sourced the script (e.g. returning 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 returnwithout 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; }
share|improve this answer

I have figured the following out by trial and error. Maybe a BASH guru can explain some more.

  1. .bashrc contents:

    test -f $HOME/existent_file || return 4
    

    After opening a new terminal:

    $ echo $?
    0
    
  2. .bashrc contents:

    test -f $HOME/non_existent_file || return 4
    

    After opening a new terminal:

    $ echo $?
    1
    
  3. .bashrc contents:

    function foo () { 
        return 4 
    }
    foo;
    

    After opening a new terminal:

    $ echo $?
    4
    
  4. .bashrc contents:

    return 4
    

    After opening a new terminal:

    $ echo $?
    0
    
  5. With the same .bashrc as above:

    $ source ~/.bashrc
    $ echo $?
    4
    
  6. 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.

share|improve this answer
    
Good detective work, leading to fascinating results! This seems to be the illustration that goes with Daniel’s answer. BTW, it shouldn’t matter, but what platform were you on? (Mac?) –  Scott Feb 16 '13 at 21:40
    
@Scott, thanks :). I'm on Linux, Linux Mint Debian to be precise and bash 4.2.36(1). –  terdon Feb 16 '13 at 22:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.