Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

In Linux and, to my knowledge, all Unix systems, terminal emulators run interactive, non-login shells by default. This means that, for bash, the started shell will:

When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist. This may be inhibited by using the --norc option.

The --rcfile file option will force bash to read and execute commands from file instead of /etc/bash.bashrc and ~/.bashrc.

And for login shells:

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.

The --noprofile option may be used when the shell is started to inhibit this behavior.

On OSX, however, the default shell (which is bash) started in the default terminal (Terminal.app) actually sources ~/.bash_profile or ~.profile etc. In other words, it acts like a login shell.

Main question: Why is the default interactive shell a login shell on OSX? Why did OSX choose to do this? This means that all instructions/tutorials for shell based things that mention changing things in ~/.bashrc will fail on OSX or vice versa for ~/.profile. Still, while many accusations can be leveled at Apple, hiring incompetent or idiotic devs is not one of them. Presumably, they had a good reason for this, so why?

Subquestions: Does Terminal.app actually run an interactive login shell or have they changed bash's behavior? Is this specific to Terminal.app or is it independent of the terminal emulator?

share|improve this question
    
yeah, um... iTerm is definitely not the default terminal emulator. that would be /Applications/Terminal.app. –  strugee Mar 14 at 1:15
    
@strugee thanks, edited. –  terdon Mar 14 at 1:17
1  
Terminal.app runs a login shell. I don't know why Apple chose to do that. –  Gilles Mar 14 at 1:29

3 Answers 3

up vote 5 down vote accepted

The way it's supposed work is that, at the point when you get a shell prompt, both .profile and .bashrc have been run. The specific details of how you get to that point are of secondary relevance, but if either of the files didn't get run at all, you'd have a shell with incomplete settings.

The reason terminal emulators on Linux (and other X-based systems) don't need to run .profile themselves is that it will normally have been run already when you logged in to X. The settings in .profile are supposed to be of the kind that can be inherited by subprocesses, so as long as it's executed once when you log in (e.g. via .Xsession), any further subshells don't need to re-run it.

As the Debian wiki page linked by Alan Shutko explains:

"Why is .bashrc a separate file from .bash_profile, then? This is done for mostly historical reasons, when machines were extremely slow compared to today's workstations. Processing the commands in .profile or .bash_profile could take quite a long time, especially on a machine where a lot of the work had to be done by external commands (pre-bash). So the difficult initial set-up commands, which create environment variables that can be passed down to child processes, are put in .bash_profile. The transient settings and aliases which are not inherited are put in .bashrc so that they can be re-read by every subshell."

All the same rules hold on OSX, too, except for one thing — the OSX GUI doesn't run .profile when you log in, apparently because it has its own method of loading global settings. But that means that a terminal emulator on OSX does need to run .profile (by telling the shell it launches that it's a login shell), otherwise you'd end up with a potentially crippled shell.


Now, a kind of a silly peculiarity of bash, not shared by most other shells, is that it will not automatically run .bashrc if it's started as a login shell. The standard work-around for that is to include something like the following commands in .bash_profile:

[[ -e ~/.profile ]] && source ~/.profile    # load generic profile settings
[[ -e ~/.bashrc  ]] && source ~/.bashrc     # load aliases etc.

Alternatively, it's possible to have no .bash_profile at all, and just include some bash-specific code in the generic .profile file to run .bashrc if needed.

If the OSX default .bash_profile or .profile doesn't do this, then that's arguably a bug. In any case, the proper work-around is to simply add those lines to .bash_profile.


Edit: As strugee notes, the default shell on OSX used to be tcsh, whose behavior is much saner in this respect: when run as an interactive login shell, tcsh automatically reads both .profile and .tcshrc / .cshrc, and thus does not need any workarounds like the .bash_profile trick shown above.

Based on this, I'm 99% sure that the failure of OSX to supply an appropriate default .bash_profile is because, when they switched from tcsh to bash, the folks at Apple simply didn't notice this little wart in bash's startup behavior. With tcsh, no such tricks were needed — starting tcsh as a login shell from an OSX terminal emulator Just Plain Works and does the right thing without such kluges.

share|improve this answer
    
Thanks, I sort of knew all that. My question is why did OSX choose to set up in such a way as to render .bashrc irrelevant? Why did they choose to make all shells login shells? As far as I can tell, only your last sentence addresses that and only to say that it's a bug. –  terdon Mar 14 at 15:31
    
If OSX ships creates a default .profile / .bash_profile that doesn't source .bashrc, then yes, I'd definitely call that a bug. If they don't create any of those dotfiles by default at all, then it could be argued to be just an omission (i.e. "if you use dotfiles, you're responsible for setting them up correctly"), although, IMO, there's still no good reason for any system using bash as a standard shell not to automatically create a basic .bash_profile like shown above. –  Ilmari Karonen Mar 14 at 16:50
    
No, the issue is that they start login shells in their terminal emulators. The dotfiles are default bash behavior, starting login shells will read profile etc, not bashrc etc. The question is why login shells are run instead of non-login ones. –  terdon Mar 14 at 16:53
1  
Yes, and both I and Alan have explained that it's because, unlike Linux, OSX doesn't execute .profile when the user logs into the GUI, so they have to execute it later to get environment variables like $PATH, which are normally set in .profile, configured correctly. The fact that, as a side effect, this causes .bashrc not to be sourced is a bug; you can argue about whether it's a bug in bash or in OSX, but that doesn't change the fact that the correct behavior would be to ensure that both the environment variables from .profile and the bash config setting from .bashrc are loaded. –  Ilmari Karonen Mar 14 at 17:01
    
Ps. See also these related questions from Ask Different, Super User, Ask Ubuntu and Stack Overflow. –  Ilmari Karonen Mar 14 at 17:03

The main reason that X terminal applications run non-login shells by default is that in the beginning of time, your .Xsession would have run the .profile to set up your initial login items. Then, since that was all set up already, terminal apps didn't need to run it, they could run the .bashrc. Discussion of why this would matter is at https://wiki.debian.org/DotFiles:

Let's take xdm as an example. pierre comes back from vacation one day and discovers that his system administrator has installed xdm on the Debian system. He logs in just fine, and xdm reads his .xsession file and runs fluxbox. Everything seems to be OK until he gets an error message in the wrong locale! Since he overrides the LANG variable in his .bash_profile, and since xdm never reads .bash_profile, his LANG variable is now set to en_US instead of fr_CA.

Now, the naive solution to this problem is that instead of launching "xterm", he could configure his window manager to launch "xterm -ls". This flag tells xterm that instead of launching a normal shell, it should launch a login shell. Under this setup, xterm spawns /bin/bash but it puts "-/bin/bash" (or maybe "-bash") in the argument vector, so bash acts like a login shell. This means that every time he opens up a new xterm, it will read /etc/profile and .bash_profile (built-in bash behavior), and then .bashrc (because .bash_profile says to do that). This may seem to work fine at first -- his dot files aren't heavy, so he doesn't even notice the delay -- but there's a more subtle problem. He also launches a web browser directly from his fluxbox menu, and the web browser inherits the LANG variable from fluxbox, which is now set to the wrong locale. So while his xterms may be fine, and anything launched from his xterms may be fine, his web browser is still giving him pages in the wrong locale.

On OS X, the user environments aren't started by a pile of shell scripts, and launchd doesn't source .profile at any time. (That's sort of a shame, since it means it's a lot more annoying to set environment variables, but such is life.) Since it doesn't, when would it run .profile? Only if you ssh'd in? That seems kind of pointless, since many boxes will never be targets of ssh. Might as well make the terminals run login shells by default, so that .profile will be run sometime.

What about .bashrc, then? Is it useless? No. It still has the purpose that it had in the days of the VT100. It is used for any time you open a shell other than opening a Terminal window. So if you shell out of Emacs or vi, or if you do a su user.

share|improve this answer
    
The Debian page you're quoting explains why Debian's .profile sources .bashrc, not why OSX decided to make all shells login shells by default. Actually, you are answering another question of mine, and thanks! However, your answer does not explain the OSX choice and the Debian quote is completely irrelevant here as far as I can tell (please let me know if I'm just missing the point). The OSX way make .bashrc etc useless and does not make .profile any more useful. –  terdon Mar 14 at 4:28
    
Thanks for a very interesting answer! –  Jenny D Mar 14 at 10:27

I don't know why they would have done that. However, here's my guess.

To start with, it's worth noting that on a GNU/Linux system, you can of course switch to vt1, vt2, etc. You get a login shell there. On an OS X system, there's no equivalent. The only way to access the UNIX underpinnings is through a terminal emulator or through single user mode (disclaimer: I've never actually used single user mode; it's commandline-driven IIRC but I may be wrong). Therefore, in OS X whatever the default is in the emulator is the default for the entire system.

Now, why would you make the default a login shell? There are a couple (read: not many) reasons I can think of to do this.

  • It provides a consistent user experience if you SSH into the box. (Especially important for the server edition of OS X - presumably if you're running an OS X server, you're a newbie.)
  • The default shell of OS X used to be tcsh. This is about as wild a guess as you can get, but it may be that tcsh normally did something when run as a login shell, and the historical pattern stuck. (I doubt it, though - maybe one of the older regulars could tell us.)
  • "We are Apple. We are the vendors of the largest UNIX distribution on the planet. It doesn't matter how trivial our reasons are; if we make a decision, your tool must deal with it."

Honestly, I've been using Darwin for ~6 years and I can't answer this question properly. It doesn't really make sense to me, either.

To answer your subquestion, bash is not patched or anything (at least for this). The default terminal emulator runs login shells by default, and presumably iTerm copies that.

share|improve this answer
1  
+1 for mentioning tcsh, since its behavior is far saner in this respect than that of bash: when started as an interactive login shell, tcsh sources both .profile and .tcshrc / .cshrc without requiring any kluges like the one I gave in my answer. Given that, I suspect this behavior is an unfixed regression caused by the switch from tcsh to bash. –  Ilmari Karonen Mar 14 at 17:09

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.