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?

Asked By: Rustacean

||

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 makes bash 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.

Answered By: aviro
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.