principlebashModerate
Environment Variables: /etc/environment vs .bashrc vs .profile
Viewed 0 times
environment variables.bashrc.profile/etc/environmentlogin shellsystemd environmentPAM
linux
Problem
Environment variables set in one location are not visible in another context — variables work in interactive shells but not in SSH sessions, cron, or systemd services.
Solution
Understand the load order and use the correct file for each scope.
# /etc/environment — system-wide, simple KEY=VALUE, no shell syntax
# Read by PAM on login, available in ALL sessions including GUI
JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
# /etc/profile.d/*.sh — system-wide, shell syntax allowed, login shells only
# /etc/profile sources all .sh files from this directory
echo 'export GOPATH=/usr/local/go' > /etc/profile.d/golang.sh
# ~/.profile — user login shell (sourced once per login)
# ~/.bashrc — user interactive non-login shell (sourced each new terminal)
# ~/.bash_profile — overrides ~/.profile if it exists
# For systemd services: set in unit file or EnvironmentFile
# /etc/systemd/system/myapp.service
# [Service]
# EnvironmentFile=/etc/myapp/env
# Environment=NODE_ENV=production
# Reload without logout
source ~/.bashrc
exec bashWhy
Shell startup files are context-dependent. Login shells read .profile; interactive non-login shells read .bashrc. systemd services don't read any of them. /etc/environment is the only truly global option but supports no shell syntax.
Gotchas
- /etc/environment does not support shell expansion —
PATH=$PATH:/new/pathdoes not work there. - Variables set in ~/.bashrc are not inherited by child processes that don't source it.
- SSH non-interactive sessions (used by rsync, scp) source neither .bashrc nor .profile.
- Docker ENV instructions set container environment but don't affect the host.
Revisions (0)
No revisions yet.