So you need to set environment variables in Linux huh? Been there. That moment when you're installing Java or setting up a dev environment and suddenly you're staring at terminal errors because $PATH isn't cooperating. Let's talk real talk about Linux environment variables - no textbook fluff, just what actually works from someone who's messed this up more times than I'd like to admit.
Remember last month? I wasted two hours because my .bashrc edits weren't applying to VSCode. Turns out I forgot that graphical apps don't always see shell variables. We'll cover that landmine later.
What Even Are Linux Environment Variables?
Think of them as sticky notes your system uses to remember important stuff. Like telling apps where to find Java (JAVA_HOME), or where to look for programs (PATH). They're just key-value pairs living in memory:
HOME=/home/john
EDITOR=nano
Ever tried running a script and got "command not found"? That's usually PATH acting up. Or seen a Java install fail because it can't find JDK? That's JAVA_HOME missing. These little things cause big headaches.
Why Would You Need to Set Environment Variables in Linux?
A few real scenarios:
- Your Python script keeps crashing because it can't find the API key (store it in
API_KEY) - Docker compose won't start because database paths are wrong (use
DB_PATH) - You're tired of typing
/opt/myapp/bin/start.shevery time (add toPATH)
Personally, I set them constantly - for development configs, server secrets (though be careful!), and custom tool locations. Way cleaner than hardcoding paths everywhere.
Setting Environment Variables in Linux: Temporary vs Permanent
Here's where newcomers get tripped up. That variable you set? It might disappear faster than donuts in the break room.
The Quick and Dirty Way (Temporary)
Need something just for this terminal session? Easy:
Try it now: Run export TEST=hello then echo $TEST. See? Works. Now close terminal and poof - gone. Good for testing, terrible for anything persistent.
Watch out: Variables set this way don't affect child processes if you use the syntax MY_VAR=value ./script.sh. That variable only exists for that single command!
Making Environment Variables Stick (Permanent)
Ah, the real magic. Where you set them changes who sees them:
| File | Scope | When It Loads | My Preference? |
|---|---|---|---|
| ~/.bashrc | Just you | Every new terminal | ? Best for dev tools |
| ~/.profile | Just you | Login shells only | When I care about login vs non-login |
| /etc/environment | All users | System-wide at login | ? For server-wide paths |
| /etc/profile.d/*.sh | All users | Every interactive shell | Cleanest for system-wide |
Here's how I set my PATH in ~/.bashrc:
export PATH="$PATH:/home/john/bin"
After editing? Always run source ~/.bashrc or just reopen your terminal.
Confession time: I dislike /etc/environment because it doesn't support export commands - just raw VAR=VAL pairs. Annoying when you need dynamic values.
Step-by-Step: How to Set Environment Variables in Linux Correctly
Let's walk through a real example - say we're adding a Python virtualenv path:
nano ~/.bashrc (or use vim if you're fancy)
export MY_PYTHON_ENV="/home/john/.virtualenvs/myproject"
source ~/.bashrc
echo $MY_PYTHON_ENV → Should show your path
But what if it doesn't show?
Last Tuesday I set a variable that wouldn't appear. Turns out I had a typo: exprot instead of export. Bash just ignored it silently. Always double-check!
Setting Environment Variables for All Users
Say you're configuring a server and need JAVA_HOME for everyone:
Create a new file in /etc/profile.d/ (I prefer this over messing with /etc/profile):
Add:
export PATH="$PATH:$JAVA_HOME/bin"
Save. Now every new login sees Java. Test with a new user account.
10-java.sh to control order.
Critical Environment Variables You Absolutely Need to Know
Some variables do heavy lifting:
| Variable | What It Does | Typical Value | Why Care? |
|---|---|---|---|
| PATH | Where to find executables | /usr/bin:/bin | Most common troubleshooting headache |
| HOME | Your home directory | /home/username | Essential for scripts locating user files |
| USER | Current username | john | Scripts that need to know who's running them |
| EDITOR | Default text editor | nano or vim | When git asks you to edit commit messages |
| JAVA_HOME | Java installation path | /usr/lib/jvm/java-11 | Required by almost all Java tools |
| LD_LIBRARY_PATH | Where to find libraries | /usr/local/lib | Fix "shared library not found" errors |
Fun story: Last year I spent 3 hours debugging why a Python lib wouldn't load. Turns out I'd set LD_LIBRARY_PATH in .bashrc but forgot Ubuntu's GUI launchers ignore it. Had to add it to ~/.profile instead.
Troubleshooting: When Setting Environment Variables in Linux Goes Wrong
Let's diagnose common issues:
"I set it but it's not working!"
• Did you source the file after editing?
• Check for typos with printenv | grep VAR
• Trying to access from GUI? Most desktop environments don't load .bashrc
"Changes break my terminal!"
• Accidentally deleted PATH? Boot into recovery mode and fix the file
• Added broken syntax? Check with bash -x ~/.bashrc for errors
"Variable shows in terminal but not in my app!"
• Apps launched from GUI often use different configs
• Try setting in ~/.profile instead of .bashrc
• For systemd services, set in service files instead
•
printenv - Show all environment variables•
echo $MY_VAR - Check specific variable•
env - Similar to printenv•
set - Shows shell variables tooAdvanced Stuff: What Most Guides Don't Tell You
After a decade of sysadmin work, here's my hard-earned knowledge:
Security Considerations
Never do export DB_PASSWORD="secret" in plain text files! Use:
- Encrypted config managers like Hashicorp Vault
- Per-application secret files (with proper permissions!)
~/.bashrcis world-readable? Runchmod 600 ~/.bashrc
GUI Applications & Desktop Launchers
Biggest headache in Linux! Your beautiful .bashrc variables mean nothing to:
• Apps launched from desktop icons
• Scheduled cron jobs
• Systemd services
Solutions:
• For GUI apps: Set variables in ~/.profile or ~/.pam_environment
• For cron: Set vars directly in crontab
• For systemd: Use Environment= in service files
Dynamic Variables
Need today's date in a variable? Possible!
Works in .bashrc but not in /etc/environment. Tradeoffs.
Frankly I wish Linux had a unified way to set environment variables instead of this file soup. But hey, it works.
Environment Variables vs Shell Variables - What's the Diff?
Quick distinction:
export GLOBAL_VAR="I'm visible to child processes too"
That export command is what makes it an environment variable. Without it, subcommands won't see it.
The FAQ Section: Actual Questions People Ask
A: Edit
~/.bashrc for terminal sessions or ~/.profile for GUI apps. Use the export command.
Q: Where to set environment variables in Linux that affect all users?A:
/etc/environment for simple variables or create .sh files in /etc/profile.d/ for complex ones.
Q: Why can't my Ubuntu GUI programs see my environment variables?A: Desktop environments don't load .bashrc. Use
~/.profile instead, or configure via ~/.config/environment.d/ on systemd systems.
Q: How to see all currently set environment variables?A: Run
printenv or just env in terminal.
Q: Can I set environment variables for Docker containers?A: Absolutely! Use
-e MY_VAR=value in docker run, or the environment: section in docker-compose.yml.
Q: What's the difference between .bashrc and .profile?A: .bashrc loads for every new bash terminal, .profile loads only when you log into the system. Use .profile for GUI-related variables. Q: How do I remove an environment variable?
A:
unset MY_VAR for current session, or remove from config files and source again.
My Dirty Little Environment Variable Secrets
After years of trial and error:
- I create
~/.envfor project-specific vars and source it manually - keeps things isolated - Prefix all custom variables with MY_ (like MY_PROJECT_PATH) to avoid collisions
- For servers, I store environment variables in /etc/opt/myapp/config instead of profile.d - safer for updates
- Always back up config files before editing! I once corrupted .bashrc and couldn't even open terminal
And my biggest pet peeve? When guides tell you to set environment variables in Linux using /etc/profile - that file gets overwritten on upgrades! Use /etc/profile.d/ instead.
Beyond Basics: Cool Environment Variable Tricks
Level up with these:
Conditional Variables
Only set if directory exists in .bashrc:
export PATH="$PATH:/opt/special_tools"
fi
Alias Shortcuts
Combine with aliases for power moves:
alias pj="cd $PROJECTS"
Version Switching
Quickly change between tool versions:
use_java11() {
export JAVA_HOME="/usr/lib/jvm/java-11"
}
use_java17() {
export JAVA_HOME="/usr/lib/jvm/java-17"
}
Call it: use_java17 and boom - switches versions.
Final Reality Check
Look, setting environment variables in Linux feels messy because it is messy. There's no one right way - it depends on your distro, whether you're using GUI, and what needs the variable.
My practical advice?
- For personal dev work: ~/.bashrc is your friend
- For system services: Use service-specific configs
- For GUI apps: ~/.profile or distro-specific locations
- When in doubt:
printenvis the truth-teller
Don't stress about perfection. I've set environment variables incorrectly more times than I've cooked edible rice. The key is understanding why it failed when it does. Now go make that JAVA_HOME behave!
Comment