Why does Bash behave differently when compiled from source code?
I ran
git clone https://git.savannah.gnu.org/git/bash.git
cd bash/
./configure
make
./bash
I noticed that the newly launched Bash instance did not inherit the environment, specifically the PS1 variable that defines the shell prompt, from the parent shell.
The inheritance works for /bin/bash
List of sourced files is the same for /bin/bash
and ./bash
./bash -lixc exit 2>&1 | sed -n 's/^+* (source|.) //p'
/bin/bash -lixc exit 2>&1 | sed -n 's/^+* (source|.) //p'
Edit:
As aviro mentiond PS1 was defined without export, so when I tried exporting it got inherited, so my initial question was wrong.
On my machine PS1 is defined in two files
/etc/bash/bashrc
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
[[ $DISPLAY ]] && shopt -s checkwinsize
PS1='[u@h W]$ '
And /etc/bash/bashrc.d/artix.bashrc
if ${use_color} ; then
if [[ ${EUID} == 0 ]] ; then
PS1='[ 33[01;31m][h[ 33[01;36m] W[ 33[01;31m]]$[ 33[00m] '
else
PS1='[ 33[01;36m][u@h[ 33[01;37m] W[ 33[01;36m]]$[ 33[00m] '
fi
else
if [[ ${EUID} == 0 ]] ; then
# show root@ when we don't have colors
PS1='u@h W $ '
else
PS1='u@h w $ '
fi
fi
When I ran ./bash
the PS1 is s-v$
and I have no idea why.
The command listing all sourced file shows that both of these files should be sourced when run with ./bash
, but for some reason they aren’t or shell starts in different type/mode. Why?
First, you need to understand that PS1
is usually a
shell variable, which means it isn’t inherited by the children. So unless you explicitly ran export PS1=...
and made PS1
an environment variable, every new bash
process will get the PS1
(and other shell variables) from the rc files and not from the parent. So you first need to find out where exactly your PS1
is defined.
You can verify that by exporting your PS1
:
export PS1
And then run your ./bash
. You’ll see that in that case, PS1
will be inherited by the new shell.
So why doesn’t your compiled bash
get the PS1
shell variable you expect from the rc files?
Here’s my guess: On many systems, PS1
is being defined in /etc/bash.bashrc
. But not all bash
versions read this file. It depends on how bash
was being compiled. A good rule of thumb would be checking your bash
man pages. For instance, for Ubuntu you’ll see:
When an interactive shell that is not a login shell is started,
bash reads and executes commands from/etc/bash.bashrc
and~/.bashrc
,
if these files exist. This may be inhibited by using the--norc
option. The--rcfile
file option will force bash to read and execute
commands from file instead of/etc/bash.bashrc
and~/.bashrc
.
However, /etc/bash.bashrc
is not even mentioned in the bash
man page you downloaded from that [git]:
When an interactive shell that is not a login shell is started, bash
reads and executes commands from~/.bashrc
, if that file exists. This
may be inhibited by using the--norc
option. The--rcfile
file option
will force bash to read and execute commands from file instead of
~/.bashrc
.
Additionally, in the README
file of bash
from Debian, you’ll see:
5. What is
/etc/bash.bashrc
? It doesn’t seem to be documented.The Debian version of bash is compiled with a special option
(-DSYS_BASHRC
) that makesbash
read/etc/bash.bashrc
before~/.bashrc
So in the git
repository you’ve used, you’ll see at
config-top.h
that the line that defines SYS_BASHRC
is commented out by default.
/* System-wide .bashrc file for interactive shells. */
/* #define SYS_BASHRC "/etc/bash.bashrc" */
So your bash
as it’s built by default won’t read /etc/bash.bashrc
on startup, and if your PS1
is defined there, it won’t get it.
If you remove the comment from this line:
#define SYS_BASHRC "/etc/bash.bashrc"
and run make
again, my guess is that your new bash
will show the PS1
variable you expect.