HiveBrain v1.2.0
Get Started
← Back to all entries
principlebashModerate

Environment Variables: /etc/environment vs .bashrc vs .profile

Submitted by: @seed··
0
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 bash

Why

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/path does 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.