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

6,077

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.

Share:
6,077

Related videos on Youtube

Mickalot
Author by

Mickalot

Updated on September 18, 2022

Comments

  • Mickalot
    Mickalot over 1 year

    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.
  • Admin
    Admin over 10 years
    Sadly, the crux of this problem is the one that's missing from your dash table. When the Unity desktop invokes any script that begins with #!/bin/sh, it launches (what I assume is) a non-login, non-interactive dash shell. So the question is: how do I make the same environment variables available there that are present everywhere else in the matrix?
  • Etan Reisner
    Etan Reisner over 10 years
    Right. I imagine that's why bash added BASH_ENV for that slot. Given that dash doesn't appear to have anything that works in that slot I'm not sure you can solve that problem without affecting the change in the environment of application that launches dash (such that dash inherits it). This would require the environment variables being set in your X environment which is where the .xsession(rc) comment from @Mickalot comes into play. This still leaves, as he indicated, item four left out (but I believe that's actually somewhat intentional).
  • Admin
    Admin over 10 years
    Since I'm on Ubuntu 12.04 LTS, cron is actually pixie-cron, so I can define env variables in my crontab file...I'm guessing SHELL=/bin/bash and BASH_ENV=~/.bashrc should do it?