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:
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.
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! – Billy McCloskey – 2016-07-17T13:38:28.210
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 – Billy McCloskey – 2016-07-17T13:48:32.443
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. – Billy McCloskey – 2016-07-17T13:53:55.897
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 – 2017-11-25T14:35:26.630Mac OS X 10.13.1, which I installed recently, has a pre-installed
/etc/bashrc
file. – Billy McCloskey – 2017-11-28T04:41:30.330On Mac OS X 10.13.1, there is an interesting file,
/etc/bashrc_Apple_Terminal
. Since I'm using iTerm2, I'm not jumping into this "supplemental bashrc file", but it does have some interesting techniques that may prove useful. – Billy McCloskey – 2017-11-28T05:08:30.650