What's the difference between login as user and changing users using su through root?

SSH starts a login shell. su, by default does not.

In particular, this means that the ~/.profile (or similar file) for that user is not sourced. So changes made in ~/.profile won't take effect. It might also be the case that:

  • even if you start a login shell, different changes were made in root's ~/.profile, which might pollute the user's environment.
    • /etc/profile and /etc/profile.d/* may apply settings differently for different users (not by default, though)
  • there might be different settings for different users in SSH configuration.
  • PAM configuration is different. For example, /etc/pam.d/ssh has:

    session    required     pam_env.so user_readenv=1 envfile=/etc/default/locale
    

    whereas /etc/pam.d/su has:

    session       required   pam_env.so readenv=1 envfile=/etc/default/locale
    

    This means SSH loads ~/.pam_environment, but su doesn't. This is a big one, since ~/.pam_environment is the shell-independent place for environment variables, and it is applied if you login from the GUI, the TTY or SSH.

To start a login shell, run either of:

su - <username>
sudo -iu <username>

Example:

# su muru -c 'sh -c "echo $HOME $PATH"'
/home/muru /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
# su - muru -c 'sh -c "echo $HOME $PATH"'
/home/muru /home/muru/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
# sudo -iu muru sh -c 'echo $HOME $PATH'
/home/muru /home/muru/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# sudo -u muru sh -c 'echo $HOME $PATH'
/root /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# ssh muru@localhost 'echo $HOME $PATH'
/home/muru /home/muru/devel/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Even with SSH, if you run a command instead of starting a shell, a login shell won't be run (note the absence of ~/bin in the SSH test, which is present in su - and sudo -i). To get the true result, I will run my shell as a login shell:

# ssh muru@localhost '$SHELL -ilc "echo \$HOME \$PATH"'
/home/muru /home/muru/bin:/home/muru/devel/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

This is also why sudo su and sudo -s are crappy ways of getting a root shell. Both these ways are polluted by the environment.


Related:

  • Unix & Linux: su vs sudo -s vs sudo -i vs sudo bash

Tags:

Ssh

Sudo

Su