When administering CentOS/RHEL systems, many administrators encounter a puzzling scenario:
$ su Password: # ifconfig bash: ifconfig: command not found # exit $ su - Password: # ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
The critical difference lies in how environment variables are handled:
- su: Preserves the original user's environment (shell variables, PATH, etc.)
- su - or su -l: Simulates a full login, loading the target user's environment
Let's examine the PATH differences with concrete examples:
# As regular user $ echo $PATH /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin # After 'su' without hyphen $ su # echo $PATH /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin # Same as original user # After 'su -' $ su - # echo $PATH /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # Root's default PATH
The environment difference stems from these critical files:
/etc/profile /etc/bashrc ~/.bash_profile ~/.bashrc
When using su -, the system reads all these files sequentially, while plain su only processes:
/etc/bashrc ~/.bashrc
Consider these real-world scenarios:
# Dangerous scenario with plain 'su' $ su # rm -rf /tmp/some_dir/* # If PATH compromised, 'rm' could be aliased/malicious # Safe alternative $ su - # rm -rf /tmp/some_dir/* # Uses root's clean environment
- Always prefer
sudo
for single commands when possible- Use
su -
when needing full root environment- For scripting:
su -c 'command' - root
provides proper environmentWhen debugging environment problems:
# Compare environments $ su -c 'env | sort > /tmp/root_env' $ env | sort > /tmp/user_env $ diff /tmp/user_env /tmp/root_env
When you execute
su
to become root in CentOS, you might encounter unexpected behavior like this:$ su Password: # ifconfig bash: ifconfig: command not found
Yet when you use
su -
, everything works:$ su - Password: # ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.100 netmask 255.255.255.0 broadcast 192.168.1.255
The fundamental difference lies in how environment variables are handled:
su
: Maintains the original user's environment (PATH, HOME, etc.)su -
orsu -l
: Starts a login shell with root's environment
You can verify this by checking environment variables after each command:
$ su
# echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
$ su -
# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
This behavior affects several common scenarios:
- System binaries access: /sbin and /usr/sbin aren't in regular users' PATH
- Configuration files: ~/.bashrc and ~/.profile aren't sourced with plain
su
- Service management: Commands like
systemctl
might behave differently
For scripting purposes, always explicitly specify which version you need:
#!/bin/bash
# For full root environment
su - root -c "/sbin/ifconfig eth0 down"
# For minimal environment change
su root -c "echo \$PATH"
While su -
provides more complete root functionality, it also:
- Loads root's shell configuration files (potential security risk if modified)
- Changes the working directory to /root
- Makes environment changes that might affect script behavior
For automated tasks, consider using sudo
instead for better auditing:
sudo /sbin/ifconfig eth0 down
The distinction dates back to original Unix implementations where:
su
was designed for quick privilege escalationsu -
was meant for full login sessions
In modern practice, many administrators prefer sudo -i
as an alternative:
sudo -i
# Equivalent to su - but with sudo's audit trail