Hi Paul!
Paul E Condon wrote:
> I'm debugging some bash scripts and reading the scripts that come as
> part of Squeeze installation. I find several places where there are
> statements the set a value from variable PS1, BUT all of them seem
> to be in scripts that only get executed if PS1 is already non-empty.
> i.e. they are after a statement
> [ -z "$PS1" ] && return
> which, I think, executes return if PS1 is empty.
Correct. The -z is true if "$PS1" is zero length. The shell is
setting PS1 already if the shell is interactive. Therefore a quick
check of PS1 is one way to decide if the shell thinks it is
interactive or not. The shell has a non-trivial algorithm to
determine whether to be interactive or not. Really determining
whether it actually *is* interactive or not is rather hard. But if
the shell thinks it is interactive then PS1 is set. That works in a
well behaved environment. But it is possible to fool it if a user has
manually set and exported PS1. But that isn't a well behaved
environment and the solution is to correct that situation.
Another technique that I also commonly see is to look at the shell's
flags and look for the presence of the -i option. This is easily done
with a case statement. This is harder to fool than the PS1 method
above.
case $- in *i*) return ;; esac
There isn't really one canonical correct answer to the question of how
to tell if a shell is interactive or not. But one of those two
methods are most common since they are completely internal to the
shell and therefore fast and efficient operations.
[Note that the ksh book listed yet another method that uses $ENV and
array processing to effect the same goals but within the ksh
environment.]
> A related question:
> The comment just before the above line of code is:
> "# If not running interactively, don't do anything"
The goal here is that scripts should not be affected by the contents
of a user's ~/.bashrc file. If a script were to source that
environment script then the aliases, functions, and other settings
there would bring havoc upon the operation of the script. Therefore
if a script is sourcing that file try to detect it and stop it as soon
as possible.
Also, depending upon several factors, the ~/.bashrc is sourced on a
remote shell running under ssh. Meaning that if you put a function or
LANG setting, or PATH setting above that line then it will be in
effect when running a remote shell with ssh. (Or rsh in the old
days.) I set LANG above that line so that I automatically get LANG
set when running commands by ssh.
> For me, the implication of this comment is that a non-empty PS1 IS
> the defining characteristic of 'running interactively', but I would
> have thought 'interactive' should be characterized by having a tty
> attached to sysin and sysout for communication to a 'user'.
Not really. Using PS1 is just one of the quick and dirty tests that
tends to do the right thing most of the time. But I think looking at
the shell's flags in $- is more technically correct because it is
harder to fool.
> I can imagine that a non-empty PS1 is used as an indicator, in which
> case whatever code that actually sets up the tty also sets PS1 to
> some minimal non-empty value like a single space or a dot, but is
> this actually the way it works, and where is it?
The shell itself sets PS1. Different shells set different default
values. The Bourne shell set '$ ' and csh set '% ' for example. But
in most cases people override the default with their own personal
preference.
> Where can I read about these issues?
Well... The information is scattered about in a number of places.
The man pages contain most of it. The bash man page says:
An interactive shell is one started without non-option arguments and
without the -c option whose standard input and error are both connected
to terminals (as determined by isatty(3)), or one started with the -i
option. PS1 is set and $- includes i if bash is interactive, allowing
a shell script or a startup file to test this state.
PS1 The value of this parameter is expanded (see PROMPTING below)
and used as the primary prompt string. The default value is
‘‘\s-\v\$ ’’.
Bob
Attachment:
signature.asc
Description: Digital signature