这是indexloc提供的服务,不要输入任何密码
Skip to content

bash: user's ~/.bashrc shouldn't be sourced in system bash.bashrc #7981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

trolzen
Copy link

@trolzen trolzen commented Nov 13, 2021

Sourcing user's rc-file in system profile causes calling init files in the wrong order:

  1. $PREFIX/etc/profile
  2. $PREFIX/etc/bash.bashrc
  3. ~/.bashrc
  4. ~/.bash_profile or ~/.profile

While the ~/.bash_profile or ~/.profile should be called before the ~/.bashrc.

With this PR merged, a non-login interactive shell will load the ~/.bashrc anyway, and for login shell user can source it in the ~/.bash_profile or ~/.profile. The current behavior forces to make workarounds in the user's init files.

Also, it looks like the majority of Linux distros don't source user's rc-file in system profile-file.

@trolzen trolzen requested a review from a user November 13, 2021 22:28
@Grimler91
Copy link
Member

Sourcing ~/.bash_profile / ~/.profile before ~/.bashrc makes sense, and from testing this I don't notice any issues.

I don't really have a good grasp of what order, and how, the various profile and rc files are suppose to be sourced, so I would like to get a second approval opinion here (or time for me to read bash's documentation)

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, .bashrc has to be sourced after ~/.bash_profile. However Bash in interactive login mode doesn't load ~/.bashrc on its own. That's why Termux sources it in profile.

I can propose creating default .bashrc and .bash_profile scripts packaged as part of termux-tools package and modify login script (also part of termux-tools) to copy them to $HOME if they do not exist.

.bash_profile should contain at least this:

[ -f "${HOME}/.bashrc" ] && . "${HOME}/.bashrc"

Some distributions source the ~/.bashrc in /etc/profile. E.g. that's what I have on OpenSUSE installation:

if test -z "$_SOURCED_FOR_SSH" -a "$norc" != true ; then
    #
    # System BASH specials, maybe also good for other shells
    # Note that ksh always reads /etc/ksh.kshrc
    #
    if test "$is" != ksh -a "$is" != zsh ; then
    _is_save=$is
    test -r /etc/bash.bashrc && . /etc/bash.bashrc
    is=$_is_save
    unset _is_save
    fi
    if test "$restricted" = true ; then
    readonly _HOMEBASHRC=true
    fi
    if test "$is" = "bash" -a -z "$_HOMEBASHRC" ; then
    # loop detection
    readonly _HOMEBASHRC=true
    test -r $HOME/.bashrc && . $HOME/.bashrc
    fi

@agnostic-apollo
Copy link
Member

I was gonna post the comment yesterday but got busy with some other stuff to complete it.

If we are going to be changing the behaviour of startup files, best think on this from a future perspective as well.

The behaviour would depend on distros of course, but the debian/ubuntu defaults are below.

The following are provided by the base-files package.

The following are provided by the modified bash package provided by debian itself.

The /etc/bash.bashrc is not provided by GNU bash and is disabled by default and debian bash has a patch to enable it internally by defining SYS_BASHRC.

You can check the invocation order in debian manpage for debian specific order and in GNU manpage. Its handled by bash/shell.c. The SYS_PROFILE = /etc/profile, DEFAULT_BASHRC/bashrc_file = ~/.bashrc and SYS_BASHRC = /etc/bash.bashrc.

The debian logic is the following.

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

When an interactive login shell exits, or a non-interactive login shell executes the exit builtin command, bash reads and executes commands from the file ~/.bash_logout, if it exists.

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.

When bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following command were executed:

Only the first file in B is started.

File Interactive login Interactive non-login Script
/etc/profile A
~/bash_profile B1
~/.profile B2
~/bash_login B4
/etc/bash.bashrc A
~/.bashrc via ~/.profile B
BASH_ENV A
~/.bash_logout C
  1. Currently, termux is using GNU bash and not the one provided by debian but does apply some debian patches, like for /etc/bash.bashrc. Would need to look into the other patches as well to see what if any missing differences exist.

  2. Termux is running /etc/profile.d/*.sh before sourcing /etc/bash.bashrc, which is the wrong order, so at least that should be fixed.

  3. I agree with the removal of sourcing of ~/.bashrc done in /etc/profile, that is not the place for it and bash will automatically call it for interactive non-login shells. Sourcing it in ~/.profile for interactive login shells should be setup manually by the user or as part of bootstrap/termux-tools setup as per debian config. By default only ~/.profile and ~/.bashrc exist in debian/ubuntu. The ~/.bash_profile does not exist but a sample file is provided by adduser package. So we can technically install some default files in bootstrap/termux-tools setup.

  4. There is no [ "${PS1-}" ] check in termux /etc/profile as there is in debian /etc/profile. The ${PS1-} expansion is needed due to this. The bash default PS1/PPROMPT is \s-\v\$ and should be set to $PS1 variable during shell initialization.

  5. The termux /etc/bash.bashrc does not automatically return if PS1 is not set. It's not supposed to run for non-interactive shells.

  6. There should be an explicit check for if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ] like done in debian /etc/bash.bashrc before termux /etc/bash.bashrc sets the PS1. Otherwise, it causes problems described at https://github.com/agnostic-apollo/sudo#ps1, where PS1 is overridden. If this gets fixed, then both tudo/sudo can use SUDO_PS1 to prevent overwrite instead of users having to modify default startup files.

  7. This is more of philosophical point. Should every new terminal started by termux be an interactive login shell instead of just being an interactive shell? Although, not sure how inheritance would be done of env variables, etc from login shells into non-login shells, since termux app itself is not a login shell. So likely not possible for termux. Seems like OSX runs a login shell for every terminal too https://unix.stackexchange.com/questions/119627/why-are-interactive-shells-on-osx-login-shells-by-default.

I don't think these changes should affect any "systemd" implementation that is done in termux app in future. Systemd does not run any startup files and has its own environment files. https://unix.stackexchange.com/a/455283

@ghost
Copy link

ghost commented Nov 23, 2021

What I'm proposing is to just provide bootstrap rc files (like /etc/skel on Linux distributions) that will be placed into $HOME on first login or if not exist, in addition to fix order. However rc files, whether this is ~/.profile or ~/.bash_profile should load ~/.bashrc on interactive login shell if exist and without additional inputs from user.

Should every new terminal started by termux be an interactive login shell instead of just being an interactive shell?

Yes, it should be login shell for every opened terminal as we don't have other way to "log in". On Linux distribution login shell is started when user logged in through TTY console or SSH and terminal emulators start the non-login shell by default.

@agnostic-apollo
Copy link
Member

agnostic-apollo commented Nov 23, 2021

whether this is ~/.profile or ~/.bash_profile should load ~/.bashrc on interactive login shell

Agreed, this should be ~/.profile as per debian, with check for $BASH.

https://sources.debian.org/src/base-files/11.1+deb11u1/share/dot.profile/#L5

other way to "log in".

Yeah, already get all that... I was just talking from the perspective of login shell stuff being run every time. Do plan on exporting an ENV variable from termux-app for session count till now if login shell is started (not RUN_COMMAND). Users can at least use that.

@ghost ghost marked this pull request as draft November 27, 2021 12:25
@stale
Copy link

stale bot commented Jan 11, 2022

This issue/PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix Issue won't be fixed label Jan 11, 2022
@stale stale bot removed the wontfix Issue won't be fixed label Jan 11, 2022
@xtkoba xtkoba removed the not stale label Dec 24, 2022
@twaik
Copy link
Member

twaik commented Apr 24, 2024

This PR seems to be 2.5 years old. Should we keep it open or we can close it?

@agnostic-apollo
Copy link
Member

Will need to be eventually worked on, so fine to keep open.

@nero
Copy link

nero commented Dec 15, 2024

Loading the bashrc from the system profile is problematic because it invokes the bashrc before the environment from the user profile is loaded. Conditionally sourcing the bashrc should happen from the user profile, which can be deployed to user homes via the /etc/skel mechanism.

nero added a commit to nero/dotconfig that referenced this pull request Dec 15, 2024
Bash doesn't load the bashrc for interactive login shells. As work-around
for that, the bashrc is sourced by the user profile. This is both debian default
and my behavior. Termux put the code incorrectly into the *global* profile,
resulting in the bashrc being invoked before the user profile has loaded.
With ENV not being set, the bashrc throws an error.

Work-around until termux/termux-packages#7981 is merged and shipped.
@robertkirkman robertkirkman linked an issue Jul 7, 2025 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: ~/.bashrc is sourced by $PREFIX/etc/profile
6 participants