5

On RHEL7 I see a different behaviour with startup scripts when I su to a user with /bin/sh or /bin/bash as the shell, despite the fact that /bin/sh points to /bin/bash

I've got the following scripts set up for the user:

/home/my_user/.profile

echo Hello from .profile

/home/my_user/.bash_profile

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

echo Hello from .bash_profile

/home/my_user/.bashrc

# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions
echo Hello from .bashrc

Now when I su and specify /bin/bash I get the following output.

[batwad@hellodave ~]$ sudo su -s /bin/bash my_user
Hello from .bashrc
[my_user@hellodave batwad]$

Does this mean .bash_profile wasn't executed? After all, I don't see "Hello from .bash_profile"

Now when I su and specify /bin/sh (which links to /bin/bash anyway) I get the following output.

[batwad@hellodave ~]$ sudo su -s /bin/sh my_user
sh-4.2$

No echoes and a different shell prompt. What gives?

Update

Following redseven's answer I tried adding -l and got yet another behaviour!

[bawtad@hellodave ~]$ sudo su -l -s /bin/sh my_user
Last login: Thu Aug 16 11:44:38 UTC 2018 on pts/0
Hello from .profile
-sh-4.2$

It's .profile that is used this time! Note the "Last login" part didn't appear on the first try.

1
  • Just a note, that it is not a good idea to output something is .bashrc script, as it may cause problems with scp and other tools.
    – nt86
    Commented Jun 29, 2021 at 7:40

4 Answers 4

3

I faced the same issue in Ubuntu 20.04.3 and that was because of these lines inside ~/.bashrc:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

The solution for me was to move the important commands inside ~/.bashrc before that block (basically the lines needed to load nvm and node.js).

1
  • Or something like this [[ $- != *i* ]] && return at first line
    – a55
    Commented Apr 17, 2023 at 20:56
2

If you want to use all your settings when you normally have after a login the best way to use the -l (or simple -) option for su:

man su:

       -, -l, --login
       Provide an environment similar to what the user would expect had the user logged in
       directly.

With the -l option your ~./bash_profile will be used (and your .bashrc as well if it's included into your .bash_profile), otherwise your shell is not a login shell and only the ~/.bashrc will be used.

These are only true if your shell is bash. If you have a different default shell or you specify a different shell with -s option then it all depends how that shell works (which may use or may ignore bash settings). Even if /bin/sh is a symlink to the bash binary it's a different shell, the binary detect which way you started it and starts a different shell not bash.

1
  • Cool, that yields a different behaviour again! What if I were to expand a little and give the reason for /sbin/nologin' as the user's shell is that it's a service account used to launch an application with an init script, and the su` command is part of that script? Would I want that to be a login shell?
    – batwad
    Commented Aug 16, 2018 at 11:53
1

The difference in behaviour you see is a standard feature of bash to insure a full compatibility for plain standard Bourne shell environments.

From the mouth of the standard bash man page (type /INVOCATION):

If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.

1
  • 1
    Lesson learned: if you want bash, specify /bin/bash
    – batwad
    Commented Aug 20, 2018 at 8:05
0

If the bash starts as interactive non-login shell it search for the ~/.bash_bashrc, ~/.bashrc for user-specific configuration and /etc/bash.bashrc for system wide configuration (refer to bash man page).

But if it is run as an interactive login shell(which can be done by appending --login) it first looks for ~/.profileor ~/.bash_profile(whatever is availabe.. in your case it hits the ~/.profile so it won't bother reading the ~/.bash_profile) for user-specific configuration and /etc/profile for system-wide configs

If you want to source both files add this to your .bashrc file

 if [ -f $HOME/.profile ]; then
     . /etc/profile
 fi

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .