
How to Read and Set Environmental and Shell Variables on Linux
Environmental variables and shell variables are fundamental components of Linux systems that store configuration data, system paths, and user preferences. Understanding how to read, set, and manage these variables is crucial for developers and system administrators who need to configure applications, automate deployments, or troubleshoot system issues. This guide will walk you through the technical details of working with environment variables, from basic commands to advanced configuration scenarios that you’ll encounter in production environments.
Understanding Environment vs Shell Variables
Before diving into commands, it’s important to understand the distinction between shell variables and environment variables. Shell variables exist only within the current shell session and aren’t passed to child processes. Environment variables, however, are exported to child processes and are available system-wide.
Shell variables are local to your current session:
# Setting a shell variable
MY_VAR="hello world"
echo $MY_VAR
Environment variables are exported and inherited by child processes:
# Setting an environment variable
export MY_ENV_VAR="hello world"
echo $MY_ENV_VAR
The key difference becomes apparent when you spawn a new shell or run a script. Shell variables won’t be available in the child process, but environment variables will be.
Reading Environment and Shell Variables
Linux provides several methods to view and access variables. Here are the most commonly used approaches:
Using the env Command
The env
command displays all environment variables in the current session:
# Display all environment variables
env
# Filter specific variables
env | grep PATH
# Display variables in sorted order
env | sort
Using printenv
The printenv
command is specifically designed for environment variables:
# Show all environment variables
printenv
# Show specific variable
printenv PATH
# Show multiple variables
printenv PATH HOME USER
Using set Command
The set
command shows both environment and shell variables:
# Display all variables (shell and environment)
set
# Display only environment variables (bash)
set -o posix; set; set +o posix
Accessing Variables in Scripts
In shell scripts and command line, you access variables using the dollar sign syntax:
# Direct access
echo $HOME
echo $PATH
# Using curly braces (recommended for clarity)
echo ${HOME}
echo ${PATH}
# Default values if variable is unset
echo ${MY_VAR:-"default value"}
# Check if variable is set
if [ -n "$MY_VAR" ]; then
echo "Variable is set: $MY_VAR"
else
echo "Variable is not set"
fi
Setting Environment and Shell Variables
There are multiple ways to set variables depending on your specific needs and the scope you want to achieve.
Temporary Variables (Current Session Only)
These variables exist only for the current shell session:
# Shell variable (not exported)
MY_SHELL_VAR="temporary value"
# Environment variable (exported)
export MY_ENV_VAR="temporary environment value"
# Set and export in one line
export DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"
Persistent Variables for User Sessions
To make variables persistent across login sessions, add them to shell configuration files:
# For bash users - add to ~/.bashrc
echo 'export MY_PERMANENT_VAR="persistent value"' >> ~/.bashrc
# For zsh users - add to ~/.zshrc
echo 'export MY_PERMANENT_VAR="persistent value"' >> ~/.zshrc
# Reload the configuration
source ~/.bashrc
# or
source ~/.zshrc
System-wide Environment Variables
For system-wide variables available to all users:
# Add to /etc/environment (Ubuntu/Debian)
sudo echo 'GLOBAL_VAR="system wide value"' >> /etc/environment
# Add to /etc/profile for all users
sudo echo 'export GLOBAL_VAR="system wide value"' >> /etc/profile
# Create custom file in /etc/profile.d/
sudo echo 'export CUSTOM_VAR="value"' > /etc/profile.d/custom-vars.sh
Real-world Use Cases and Examples
Here are practical scenarios where environment variables are essential:
Database Configuration
# Setting database connection variables
export DB_HOST="localhost"
export DB_PORT="5432"
export DB_NAME="production_db"
export DB_USER="app_user"
export DB_PASSWORD="secure_password"
# Using in application
psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME
API Keys and Secrets
# Setting API credentials
export API_KEY="your-secret-api-key"
export AWS_ACCESS_KEY_ID="your-aws-access-key"
export AWS_SECRET_ACCESS_KEY="your-aws-secret-key"
# Using in scripts
curl -H "Authorization: Bearer $API_KEY" https://api.example.com/data
Development Environment Setup
# Node.js environment
export NODE_ENV="development"
export PORT="3000"
# Python environment
export PYTHONPATH="/opt/myapp:$PYTHONPATH"
export FLASK_ENV="development"
# Java environment
export JAVA_HOME="/usr/lib/jvm/java-11-openjdk"
export MAVEN_HOME="/opt/maven"
export PATH="$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH"
Advanced Variable Management Techniques
Variable Substitution and Manipulation
Bash provides powerful variable manipulation capabilities:
# String length
echo ${#PATH}
# Substring extraction
echo ${PATH:0:10} # First 10 characters
echo ${PATH:10} # From 10th character to end
# Pattern matching and replacement
echo ${PATH//:/\n} # Replace all colons with newlines
echo ${PATH%:*} # Remove everything after last colon
echo ${PATH#*:} # Remove everything before first colon
# Case conversion (Bash 4+)
export UPPER_VAR="hello world"
echo ${UPPER_VAR^^} # Convert to uppercase
echo ${UPPER_VAR,,} # Convert to lowercase
Array Variables
Bash supports array variables for more complex data structures:
# Declare array
declare -a SERVERS=("web1.example.com" "web2.example.com" "web3.example.com")
# Access array elements
echo ${SERVERS[0]} # First element
echo ${SERVERS[@]} # All elements
echo ${#SERVERS[@]} # Array length
# Loop through array
for server in "${SERVERS[@]}"; do
echo "Processing server: $server"
# ping -c 1 $server
done
Conditional Variable Setting
# Set variable only if not already set
: ${PORT:=8080}
: ${DATABASE_URL:="sqlite:///default.db"}
# Set variable and export if not set
export PORT=${PORT:-8080}
export ENV=${ENV:-development}
# Require variable to be set
: ${REQUIRED_VAR:?Error: REQUIRED_VAR must be set}
Environment Variable Security Considerations
Working with sensitive data in environment variables requires careful attention to security:
Best Practices for Secrets
- Never commit environment files with secrets to version control
- Use tools like
direnv
ordotenv
for local development - Implement proper access controls on configuration files
- Use secrets management services in production environments
# Create a .env file (never commit this)
cat > .env << EOF
DATABASE_PASSWORD=super_secret_password
API_KEY=secret_api_key
JWT_SECRET=jwt_signing_secret
EOF
# Set proper permissions
chmod 600 .env
# Load variables from file (using a script)
if [ -f .env ]; then
export $(cat .env | grep -v '^#' | xargs)
fi
Using systemd for Service Environment Variables
For services managed by systemd, environment variables can be set in service files:
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/start
Environment=NODE_ENV=production
Environment=PORT=3000
EnvironmentFile=/etc/myapp/environment
Restart=always
[Install]
WantedBy=multi-user.target
Troubleshooting Common Issues
Here are solutions to frequent problems you'll encounter:
Variables Not Persisting
If variables disappear after closing the terminal:
# Check which shell you're using
echo $SHELL
# Verify the correct configuration file
ls -la ~/.bashrc ~/.bash_profile ~/.zshrc ~/.profile
# Check if files are being sourced
echo "echo 'Loading .bashrc'" >> ~/.bashrc
# Force reload configuration
source ~/.bashrc
PATH Variable Issues
When commands aren't found after modifying PATH:
# Check current PATH
echo $PATH
# Verify directory exists and has executable files
ls -la /usr/local/bin
# Add to PATH safely (avoiding duplicates)
case ":$PATH:" in
*:/usr/local/bin:*) ;;
*) PATH="/usr/local/bin:$PATH" ;;
esac
export PATH
# Reset PATH if corrupted
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Variable Expansion Problems
When variables aren't expanding correctly:
# Use quotes to preserve spaces
MY_VAR="value with spaces"
echo "$MY_VAR"
# Use single quotes to prevent expansion
echo 'The variable $HOME contains: ' "$HOME"
# Debug variable expansion
set -x # Enable debug mode
echo $MY_VAR
set +x # Disable debug mode
Performance and System Impact
Environment variables have minimal performance impact, but there are considerations for large-scale deployments:
Aspect | Impact | Recommendation |
---|---|---|
Memory Usage | ~1KB per 1000 variables | Limit to necessary variables |
Process Startup | Negligible delay | No specific optimization needed |
Inheritance | All exported variables copied to child processes | Unset unused variables in long-running processes |
Security | Variables visible in process lists | Use files or external secret managers for sensitive data |
Integration with Container Environments
Environment variables are crucial in containerized environments and cloud deployments:
Docker Integration
# Dockerfile
ENV NODE_ENV=production
ENV PORT=3000
# Docker run with environment variables
docker run -e NODE_ENV=production -e DATABASE_URL=postgres://... myapp
# Using environment file
docker run --env-file .env myapp
Kubernetes ConfigMaps and Secrets
# ConfigMap example
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
NODE_ENV: "production"
LOG_LEVEL: "info"
# Using in Pod
spec:
containers:
- name: app
envFrom:
- configMapRef:
name: app-config
For production deployments on dedicated infrastructure, consider using dedicated servers that provide full control over environment configuration, or VPS services for flexible containerized deployments.
Useful Tools and Utilities
Several tools can enhance your environment variable management:
- direnv: Automatically loads environment variables based on directory
- envsubst: Substitutes environment variables in template files
- dotenv: Libraries for various programming languages to load .env files
- systemd-environment-d-generator: System-wide environment variable management
# Install direnv (Ubuntu/Debian)
sudo apt install direnv
# Create .envrc file in project directory
echo 'export DATABASE_URL="postgresql://localhost/mydb"' > .envrc
direnv allow
# Using envsubst for template processing
echo 'Database: ${DATABASE_URL}' | envsubst
For additional information on environment variable best practices, consult the GNU Bash Manual and the POSIX Environment Variables specification.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.