Wandering Thoughts archives

2009-02-12

Recognizing non-interactive shells and 'shell levels'

The issue of when bash sources your .bashrc does raise the obvious question of how you can tell in your .bashrc what case you're dealing with, so that you can do different things in each of them.

The traditional approach to do this is to set environment variables to signal what state you're in and how many things have been initialized. One traditional 'have I been initialized' variable is $PS1, but this has the tiny weakness that su'ing to the account from another account that already has $PS1 set will not trigger your initializations.

(To keep clutter down, your 'am I a login shell' environment variable doesn't need to be exported, and indeed can be unset immediately after you use it. Other flag variables generally need to persist into future sub-shells.)

If you need to know interactive versus non-interactive, there are two approaches. First, you can check the shell's built in $- variable to see if the 'i' flag is part of the shell's flags, and second, you can use test to see if standard input is connected to a terminal. Which test is better depends in part on what you're trying to do; for example, if you want to run stty, you really care only about whether you're hooked up to a terminal.

The good news about modern systems is that all of this is much less important than it used to be; these days the overhead of re-doing redundant initializations, even relatively complex ones, is usually pretty low.

(Netbooks and other small machines may yet change this back, of course.)

RecognizingInteractivity written at 03:51:03; Add Comment

2009-02-08

When bash sources your .bashrc

Since I just looked up the rules on when bash sources your .bashrc (and did some testing), here's the rules on what gets sourced when, for reasonably current versions of bash. Making this more confusing is that bash apparently uses heuristics for some of its decisions.

  • login shells do not source your .bashrc; they source only your profile (bash looks at various names, but I just use .profile).
  • non-login interactive shells source your .bashrc.
  • shells started by ssh to run remote commands should source your .bashrc, assuming that bash got its heuristics right to recognize that this was happening.

  • otherwise, non-interactive shells (such as those running scripts) do not source .bashrc.

(Non-login interactive shells are common in today's environments, because there are now a lot of things that start new shell sessions without bothering to make them login shells; examples include the various X terminal emulators (xterm et al) and screen. In fact in some environments all of your shells will be non-login interactive shells, and you won't really have a login shell as such.)

Various command line arguments can influence bash's idea of what its environment is, or explicitly suppress bits of this; see --login, --noprofile, and --norc.

Since shell options only affect the current shell, they need to be set in your .bashrc so that they affect non-login interactive shells. Environment variables such as $PATH could theoretically go in your profile and be inherited by subshells, but most people put them in their .bashrc too and just have their profile source their .bashrc. Plus, this is the easiest way to alter your $PATH to make things like 'ssh host private-command' work.

(On some systems this is quite important, because rsync is not on the default $PATH. Solaris 10 is one example of this.)

As far as I can see, bash provides no clear sign about what sort of environment the shell session is running in. If this matters, you are left to deduce things through various signs, none of which are necessarily entirely accurate.

(This issue came up here recently, as we were trying to work out what we needed in .bashrc and why on our Solaris 10 machines. No one could remember exactly what had to be where.)

WhenBashrc written at 00:10:16; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.