9

It sounds like most terminal emulators don't run local sessions as login by default, so they'll load bashrc rather than bash_profile. So why do most people put everything in bash_profile and have bashrc source it rather than the other way around? By "most people" I mean most people I've seen so far. Maybe it's not as widespread as I think.

Instead of putting our configuration there and having bashrc source bash_profile, wouldn't it make more sense and be more consistent with the linux community to put everything in bashrc and have bash_profile source that?

I've heard good things about iTerm2, and it sounds like that and just about every other terminal emulator out there (other than the default OSX Terminal) would end up loading bashrc when I'm running locally. Not that it matters, as long as one sources the other, but I'm confused why preferring bash_profile is the standard?

Minor side-note: I was mistaken about iTerm2. It defaults to running login sessions, just like Terminal.app, though both emulators appear to have an option that lets you alter that.

3 Answers 3

15

People source bash_profile from bashrc instead of the other way around due to local convention.

All the opinion that I've read about how one configures their startup files in bash is primarily based on local convention. The local convention usually doesn't mention the big picture in that it doesn't talk much about the non-login, non-interactive case. The funny thing is, and I've looked, but I rarely see anyone mention cron in all their talk about why to put variables in one startup file versus the other. In fact, I've not heard one comment say: "/bin/sh is there for a reason. Bash emulates the original Bourne shell, /bin/sh, when invoked as such." For one thing, and I digress slightly, this case is important to people who work with the shell not only interactively, but who provide non-interactive, non-login (unattended or background) cron scripts that need minimal shell processing i.e. background processing doesn't require the niceties of colored prompts, command history and substitution, a properly defined $TERM variable, etc.

Further and with respect to cron, what I usually see is people creating minimal search paths or calling programs fully qualified, and not knowing how to deal with output not connected to a terminal (i.e. the non-interactive, non-login bash or sh case) when working with their cron scripts. This is usually because a good understanding of the shell startup sequence isn't fully understood, which leads to a user implementing their own startup files in a manner that is inconsistent or incoherent with the conventions already established in the local /etc startup files.

Elaborating, the setup done by local convention is laid out in that particular installation and shell's /etc files. If one examines any UNIX installation's /etc files, which are invoked as part of a typical bash startup sequence, then one should create their own start-up in a manner that is complimentary to the convention established in those /etc startup files.

The Linux Documentation Project states:

/etc/skel/ The default files for each new user are stored in this directory. Each time a new user is added, these skeleton files are copied into their home directory. An average system would have: .alias, .bash_profile, .bashrc and .cshrc files. Other files are left up to the system administrator.

Though the bash manual doesn't mention these files that are commonly found in the /etc/skel directory explicitly, from what I recall, SunOS, Solaris, RedHat, Ubuntu, HP-UX, umips, & Ultrix have /etc/skel files to pattern a user's shell startup files after. OSX clearly does not - I'm using OSX 10.9.1 right now. Unfortunately, OSX doesn't give you much to go on in terms of how things should be setup in terms of convention, but since OSX is a BSD derivative, I simply used another BSD derivative, and patterned my own bash startup sequence after that, adjusting it to fit into the local conventions used in the OSX 10.9.1 /etc startup files.

An important point that was mentioned in a parallel comment is that for OSX, the convention is to start every new Terminal as an interactive login shell. This is indeed the default in OSX. There is no problem with this convention as long as the users of an installation are consistent. The default behavior for the Terminal on OSX may be changed to conform with other UNIX distribution's shell startup conventions by making the following change to the Terminal's preferences, in particular, change the setting, Shells open with: to issue the /usr/bin/login -f -l whmcclos bash -i command:

enter image description here

With all that as a background or introduction, I will segue into my best advice, for what it's worth.

My best advice:

Examine the files the admins of your UNIX distribution have put in place. Start with the following locations, if they exist. Don't forget to use the ls -a command, because some of the files begin with a dot. See how these files are used during startup, and see how your own startup files interact with them:

/etc/bashrc
/etc/profile
/etc/skel/.bash_logout
/etc/skel/.bashrc
/etc/bash.bashrc
/etc/bash_completion

Look in the bash manual for the invocation and startup sequence. It is all laid out very well.

With all that as a caveat - here is how I did things on my OSX 10.9.1 installation - Other UNIX distributions WILL be different, but what is presented below should work on most if not all UNIX distributions, but use those other UNIX distributions' convention as a guide to tailor the below for your own purposes:

.profile

# ~/.profile: executed by the command interpreter for login shells.

# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.  Note, however, that we will have a ~/.bash_profile and it
# will simply source this file as a matter of course.

# See /usr/share/doc/bash/examples/startup-files for examples.
# The files are located in the bash-doc package.

# From here on out, I basically set up my PATH, LD_LIBRARY_PATH, and anything else I'd like
# global to running programs and how those programs find their libraries.  This is shared by
# `cron`, so we really don't want interactive stuff, here.  Also, I setup my environments
# for brew, macports, and fink here, essentially with setting PATH, and invocation of those
# package initialization file as in:

# Brew and locally compiled stuff:
export PATH=/usr/local/bin:$PATH
export PATH=/usr/local/sbin:$PATH

# The following line puts gnu utilities without the prefix "g" in the path
# i.e. tar/gtar:
export PATH=$PATH:/usr/local/Cellar/coreutils/8.21/libexec/gnubin

# MacPorts shoves stuff in /opt, so to get at that stuff...
export PATH=/opt/local/bin:$PATH
export PATH=/opt/local/sbin:$PATH

# Set up for using Fink, which lives in /sw:
[ -e /sw/bin/init.sh ] && . /sw/bin/init.sh

# My stuff:
export PATH=~/perl:$PATH
export PATH=~/bin:$PATH
export PATH=.:$PATH

.bashrc

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# From here on out, I put in things that are meaningful to interactive shells, like aliases,
# `shopt` invocations, HISTORY control, terminal characteristics, PROMPT, etc.

.bash_profile

# ~/.bash_profile: executed by the command interpreter for login shells.

# Because of this file's existence, neither ~/.bash_login nor ~/.profile
# will be sourced.

# See /usr/share/doc/bash/examples/startup-files for examples.
# The files are located in the bash-doc package.

# Because ~/.profile isn't invoked if this files exists,
# we must source ~/.profile to get its settings:
if [ -r ~/.profile ]; then . ~/.profile; fi

# The following sources ~/.bashrc in the interactive login case,
# because .bashrc isn't sourced for interactive login shells:
case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

# I'm still trying to wrap my head about what to put here.  A suggestion
# would be to put all the `bash` prompt coloring sequence functions as
# described on http://brettterpstra.com/2009/11/17/my-new-favorite-bash-prompt/

So that's my two cents. Keep in mind that my examples have tried to show the control path through the startup files and avoid what any particular site's conventions may impose.

8
  • Of late, Apple has included messages in the cron man page saying that it is still supported, but Apple claims that the launch service is more flexible, I'm not abandoning cron background process, but I know that the system administrators really dislike leaving me with a control-thread when I'm not technically logged in. Get a grip. Speaking of control threads to get in, somewhere around Yosemite, the ssh port 22 has been subsumed by the launch service, and the launch service intercepts the ssh attempt, and then routes that to port 22! Jul 17, 2016 at 13:38
  • The reason I bring up the re-routine of port 22 for ssh is that sooner or later, your gonna get into rsa PGP keys and the like, and to make this comment apropos, it is essential your .bashrc and .bash_profile are setup properly, or ssh type ghost login attempts for simple service, especially with PGP encryption enabled, will FAIL miserably! So make sure you get your .bashrc and .bash_profile, etc are in place before dabbling in PGP and ssh. if a simple "ssh me@myIP ls" failed, investigate making sure you have the above .bash_profile, etc. files correct and in place, or copied from someone Jul 17, 2016 at 13:48
  • I only make the last comment in that I setup 3 ssh accounts over the last 3 months, and each time, I did all the right steps, but setup the startup shell scripts, and then spent hours trying to figure out why I had to invoke "ls" as "/bin/ls", and nothing else worked very well. Each of 3 times, I forgot to give the new user a copy of my shell startup files. And, once I did, each time, all their problems went away. So? There you go. A kind of background processing - ssh'd connections for services. Jul 17, 2016 at 13:53
  • Great answer! One thing, I see you mention a file at /etc/bashrc in addition to /etc/nash.bashrc. I was about to remove that assuming it was a mistake but I thought I'd ask. Are there any systems that ship with an /etc/bashrc file? I haven't seen one in the Linux world.
    – terdon
    Nov 25, 2017 at 14:35
  • Mac OS X 10.13.1, which I installed recently, has a pre-installed /etc/bashrc file. Nov 28, 2017 at 4:41
4

why do we put everything in bash_profile in the first place?

.profile was originally used by /bin/sh, using .profile allows backwards compatibility.

Unless you are using mac, everything isn't put in bash_profile. It is put in bashrc

wouldn't it make more sense and be more consistent with the linux community to put everything in bashrc and have bash_profile source that?

It is common to put system information into the shell that is loaded when you connect to the machine (uptime, packages needing updating, cpu temp ect...). If bashrc sourced bash_profile, you would see all that information every time you opened a new shell.

In Unix:

.bash_profile is loaded by login shells
.bashrc is loaded by interactive shells

Except for Mac, which loads the login shell for every new terminal (interactive or not)

Additional Resources

difference between bashrc and bash-profile

Where are environment variables specified

4
  • @spuder- I'm not sure what point you are making with the statement Except for Mac, which loads the login shell for every new terminal (interactive or not). I just opened a new terminal in iTerm2 and OSX Term.app, and both presented me with interactive login shells. Your point is? Jan 18, 2014 at 15:50
  • Mac is opposite most other unix's. In ubuntu the bashrc is loaded when new terminals are opened.
    – spuder
    Jan 18, 2014 at 18:27
  • OSX does do the bash startup differently; arguably, each UNIX distro has a convention established by the admin's, reflected in the /etc/skel and other /etc shell startup files, that imposes a infrastructure on the local users that varies with distro. It is difficult to make a blanket statement about what convention is right. I'd go with the local convention, and extend that. The bash manual spells out clearly when $HOME/.bashrc is invoked; for OSX, & everyone else: Interactive & non-login. It's the inherited infrastructure for shell startup that one has to deal with in the end. Jan 18, 2014 at 20:21
  • @supder- I will agree with you that OSX's Terminal.app does force every bash shell attached to it to be a login shell by default. An informed user wanting to follow the conventions used in ubuntu would simply edit the OSX Terminal.app preferences and change the Shells open with: from Default login shell to the Command (complete path): field set to /usr/bin/login -f -l userid bash -i. This will change the convention to kick off all Terminal.app as an interactive NON-login shells, like ubuntu. Regardless, it is a local convention that is different than linux, and can be worked with. Jan 18, 2014 at 23:51
3

[...] I'm confused why preferring bash_profile is the standard?

Who says it's the standard? The Bash manual itself has this to say on the subject:

So, typically, your ~/.bash_profile contains the line

if [ -f ~/.bashrc ]; then . ~/.bashrc; fi

after (or before) any login-specific initializations.

2
  • That's interesting. I've certainly got the impression that most people implement it the other way (bashrc sourcing bash_profile), but my experience is limited.
    – ivan
    Jan 18, 2014 at 16:19
  • 1
    This is true for Linux, it is opposite for Mac
    – spuder
    Jan 18, 2014 at 18:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .