Linux – Where should I export an environment variable so that all combinations of bash/dash, interactive/non-interactive, login/non-login, will pick it up

bashlinuxubuntu 12.04

Here's the motivation for the question:

I'm using Ubuntu 12.04 LTS 2 with the Unity desktop. In my .bashrc file, I append several directories to my PATH variable and define a few environment variables, such as JAVA_HOME. When I launch applications from a terminal (running bash, my default shell), this works great, but for several of the shortcuts that use the Unity launcher, they run apps that seem to be defined to use #!/bin/sh, which is aliased to /bin/dash, and they don't pick up the contents of either ~/.bashrc or ~/.profile.

I suppose I could change all of these shortcuts to use /bin/bash instead of /bin/sh to force it to pick up the .bashrc changes, but that seems really hacky.

Given that Ubuntu 12.04 (by default) aliases /bin/sh to /bin/dash and that my default shell is /bin/bash, is there a single place where I can choose to modify the PATH and define environment variables if I want them to be present under all of these circumstances:

  1. Whenever I create a non-login bash shell (using the terminal in unity)
  2. Whenever I create a login bash shell (for example, logging in remotely over ssh)
  3. Whenever I use a Unity application launcher (given that the launcher uses /bin/sh).
  4. Whenever a cron job executes (given that SHELL=/bin/sh in /etc/crontab).

If I understand correctly, I'm guessing that:

  • (1)/(2) and (3)/(4) are different because (1)/(2) are bash and (3)/(4) are dash.
  • (1) and (2) are different because the files that bash chooses to load differs depending on whether or not it is a login shell.
  • (3) and (4) are different because (3) will come at some point after I've logged in (and hence ~/.profile will have been sourced by one of its parent processes, while (4) will come at some point when I'm not logged in, and hence ~/.profile will not have been read.

(I wouldn't be surprised if other factors matter, too, such as whether or not the shell is interactive, so there are probably more combinations that I haven't even anticipated…I'm happy to have my question "improved" in that case.)

I would expect that at some point, someone must have made some sort of guide that tells you how/where to modify environment variables in a shell-independent way (or at least a dash/bash compatible way)…I just can't seem to find the right search terms to locate such a guide.

Solutions or pointers to solutions greatly appreciated!

Updated:

  • Clarification: This is the default Ubuntu user created by the 12.04 installation process, so nothing fancy. It does have a ~/.profile (that explicitly sources ~/.bashrc), and the only ~/.bash* files present are .bashrc, .bash_history, and .bash_logout…so no there's no .bash_profile.
  • Emphasis on scope: I don't really care about any shells other than the default interactive shell (bash) and any script that happens to use /bin/sh (aliased to dash), so there's no need to complicate this with anything extra for tcsh/ksh/zsh/etc. support.

Best Answer

Shell invocation is a bit of a complicated thing. The bash and dash man pages has INVOCATION sections about this.

In summary they says (there is more detail in the man page, you should read it):

When bash is                   | it reads
-------------------------------|----------
login shell                    | /etc/profile and then the first of ~/.bash_profile, ~/.bash_login or ~/.profile that exists.
                               |
interactive non-login shell    | /etc/bash.bashrc then ~/.bashrc
                               |
non-interactive shell          | The contents of $BASH_ENV (if it exists)
                               |
interactive (as "sh")          | The contents of $ENV (if it exists)

-

When dash is                   | it reads
-------------------------------|---------
login shell                    | /etc/profile then .profile
                               |
interactive shell              | The contents of ENV (it it exists, can be set in .profile as well as in initial environment)

I don't know about other shells offhand as I never use any of them. Your best bet might be to set a couple environment variables to point at the common location script and manually source that (when appropriate) in the couple of cases that doesn't cover.

Related Question