How to set and export environment variables
How to Set and Export Environment Variables
Table of Contents
1. [Introduction](#introduction)
2. [Prerequisites](#prerequisites)
3. [Understanding Environment Variables](#understanding-environment-variables)
4. [Setting Environment Variables on Windows](#setting-environment-variables-on-windows)
5. [Setting Environment Variables on macOS and Linux](#setting-environment-variables-on-macos-and-linux)
6. [Exporting Environment Variables](#exporting-environment-variables)
7. [Practical Examples and Use Cases](#practical-examples-and-use-cases)
8. [Advanced Techniques](#advanced-techniques)
9. [Common Issues and Troubleshooting](#common-issues-and-troubleshooting)
10. [Best Practices and Security Considerations](#best-practices-and-security-considerations)
11. [Conclusion](#conclusion)
Introduction
Environment variables are dynamic values that affect the way running processes behave on a computer system. They are fundamental components of operating systems that allow you to configure applications, store sensitive information like API keys, and customize system behavior without modifying application code directly.
This comprehensive guide will teach you everything you need to know about setting and exporting environment variables across different operating systems. Whether you're a developer looking to configure your development environment, a system administrator managing server configurations, or a beginner trying to understand how applications communicate with the operating system, this article provides step-by-step instructions, practical examples, and expert insights.
By the end of this guide, you'll understand how to:
- Set temporary and permanent environment variables
- Export variables for use by child processes
- Manage environment variables across different operating systems
- Implement best practices for security and maintainability
- Troubleshoot common issues with environment variable configuration
Prerequisites
Before diving into environment variable management, ensure you have:
Technical Requirements
- Basic understanding of command-line interfaces (CLI)
- Access to terminal or command prompt on your operating system
- Administrative privileges (for system-wide environment variables)
- Text editor for creating configuration files
Knowledge Prerequisites
- Familiarity with your operating system's interface
- Basic understanding of file system navigation
- Awareness of the difference between user and system-level configurations
Tools You'll Need
- Windows: Command Prompt, PowerShell, or Windows Terminal
- macOS/Linux: Terminal application
- Optional: Text editors like nano, vim, VS Code, or Notepad++
Understanding Environment Variables
What Are Environment Variables?
Environment variables are key-value pairs that provide information about the system environment to running processes. They serve as a communication mechanism between the operating system and applications, allowing programs to access configuration data, system paths, and user preferences without hardcoding these values.
Types of Environment Variables
System Environment Variables
These are set at the operating system level and are available to all users and processes. Examples include:
- `PATH`: Directories where executable files are located
- `HOME` (Unix/Linux) or `USERPROFILE` (Windows): User's home directory
- `TEMP`: Temporary files directory
User Environment Variables
These are specific to individual user accounts and only affect processes run by that user. They allow personalized configurations without affecting other users on the same system.
Process Environment Variables
These exist only for the duration of a specific process and its child processes. They're useful for temporary configurations or passing data between related processes.
How Environment Variables Work
When a process starts, it inherits a copy of its parent process's environment variables. This inheritance mechanism allows you to set variables in a shell session and have them available to programs launched from that shell.
The key concept of "exporting" variables makes them available to child processes. Without exporting, variables remain local to the current shell session.
Setting Environment Variables on Windows
Using Command Prompt
Temporary Variables (Session-Only)
To set a variable for the current Command Prompt session:
```cmd
set VARIABLE_NAME=value
```
Example:
```cmd
set API_KEY=your_secret_key_here
set DATABASE_URL=postgresql://localhost:5432/mydb
```
To view a specific variable:
```cmd
echo %VARIABLE_NAME%
```
To view all environment variables:
```cmd
set
```
Permanent Variables Using Command Prompt
For user-specific permanent variables:
```cmd
setx VARIABLE_NAME "value"
```
For system-wide permanent variables (requires administrator privileges):
```cmd
setx VARIABLE_NAME "value" /M
```
Important Note: Changes made with `setx` don't affect the current session. You need to open a new Command Prompt window to see the changes.
Using PowerShell
Temporary Variables
```powershell
$env:VARIABLE_NAME = "value"
```
Example:
```powershell
$env:API_KEY = "your_secret_key_here"
$env:NODE_ENV = "development"
```
To view a variable:
```powershell
echo $env:VARIABLE_NAME
```
Permanent Variables Using PowerShell
For user-specific variables:
```powershell
[Environment]::SetEnvironmentVariable("VARIABLE_NAME", "value", "User")
```
For system-wide variables:
```powershell
[Environment]::SetEnvironmentVariable("VARIABLE_NAME", "value", "Machine")
```
Using Windows GUI
Through System Properties
1. Right-click "This PC" or "My Computer"
2. Select "Properties"
3. Click "Advanced system settings"
4. Click "Environment Variables"
5. Add or modify variables in either "User variables" or "System variables"
Through Windows Settings (Windows 10/11)
1. Open Settings (Windows + I)
2. Go to System > About
3. Click "Advanced system settings"
4. Follow the same steps as System Properties method
Modifying the PATH Variable on Windows
The PATH variable is crucial for running executables from any location. To add a new directory:
Using Command Prompt:
```cmd
setx PATH "%PATH%;C:\new\directory\path"
```
Using PowerShell:
```powershell
$env:PATH += ";C:\new\directory\path"
[Environment]::SetEnvironmentVariable("PATH", $env:PATH, "User")
```
Setting Environment Variables on macOS and Linux
Using Bash Shell
Temporary Variables (Session-Only)
```bash
VARIABLE_NAME=value
```
Example:
```bash
API_KEY=your_secret_key_here
DATABASE_URL=postgresql://localhost:5432/mydb
NODE_ENV=production
```
To view a variable:
```bash
echo $VARIABLE_NAME
```
To view all environment variables:
```bash
env
or
printenv
```
Making Variables Available to Child Processes
Use the `export` command:
```bash
export VARIABLE_NAME=value
```
Or set and export in one line:
```bash
export API_KEY=your_secret_key_here
```
Permanent Environment Variables
User-Specific Variables
Add variables to shell configuration files in your home directory:
For Bash (~/.bashrc or ~/.bash_profile):
```bash
Open the file
nano ~/.bashrc
Add your variables
export API_KEY=your_secret_key_here
export PATH=$PATH:/new/directory/path
export NODE_ENV=development
Reload the configuration
source ~/.bashrc
```
For Zsh (~/.zshrc):
```bash
Open the file
nano ~/.zshrc
Add your variables
export API_KEY=your_secret_key_here
export PATH=$PATH:/new/directory/path
Reload the configuration
source ~/.zshrc
```
System-Wide Variables
For variables available to all users, edit system configuration files:
Using /etc/environment (Ubuntu/Debian):
```bash
sudo nano /etc/environment
```
Add variables in the format:
```
VARIABLE_NAME=value
API_KEY=your_secret_key_here
```
Using /etc/profile:
```bash
sudo nano /etc/profile
```
Add export statements:
```bash
export VARIABLE_NAME=value
export API_KEY=your_secret_key_here
```
Using Fish Shell
Fish shell has a different syntax:
```fish
set -gx VARIABLE_NAME value
```
For permanent variables:
```fish
set -Ux VARIABLE_NAME value
```
Exporting Environment Variables
Understanding the Export Command
The `export` command in Unix-like systems makes environment variables available to child processes. Without exporting, variables remain local to the current shell.
Local vs. Exported Variables
Local variable (not inherited by child processes):
```bash
MY_VAR=hello
```
Exported variable (inherited by child processes):
```bash
export MY_VAR=hello
```
Practical Export Examples
Basic Export
```bash
Set and export in separate commands
DATABASE_HOST=localhost
export DATABASE_HOST
Set and export in one command
export DATABASE_PORT=5432
```
Conditional Exports
```bash
Export only if variable is not already set
export NODE_ENV=${NODE_ENV:-development}
Export with default value
export API_TIMEOUT=${API_TIMEOUT:-30}
```
Exporting Multiple Variables
```bash
export VAR1=value1 VAR2=value2 VAR3=value3
```
Windows Equivalent of Export
In Windows, variables set in Command Prompt or PowerShell are automatically available to child processes launched from the same session. However, you can explicitly control inheritance:
PowerShell:
```powershell
Create a process with specific environment variables
$env:MY_VAR = "value"
Start-Process -FilePath "program.exe" -Environment @{MY_VAR="value"}
```
Practical Examples and Use Cases
Development Environment Configuration
Node.js Application
Create a `.env` file for local development:
```bash
.env file
NODE_ENV=development
PORT=3000
DATABASE_URL=postgresql://localhost:5432/myapp
JWT_SECRET=your_jwt_secret_here
API_KEY=your_api_key_here
```
Set these variables in your shell:
```bash
export NODE_ENV=development
export PORT=3000
export DATABASE_URL=postgresql://localhost:5432/myapp
export JWT_SECRET=your_jwt_secret_here
export API_KEY=your_api_key_here
```
Python Application
```bash
Python-specific variables
export PYTHONPATH=$PYTHONPATH:/path/to/your/modules
export DJANGO_SETTINGS_MODULE=myproject.settings.development
export FLASK_ENV=development
export FLASK_APP=app.py
```
Docker and Containerization
Docker Environment Variables
```bash
Running a container with environment variables
docker run -e NODE_ENV=production -e PORT=8080 myapp:latest
Using environment file
docker run --env-file .env myapp:latest
```
Docker Compose
```yaml
docker-compose.yml
version: '3'
services:
web:
image: myapp:latest
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
env_file:
- .env
```
CI/CD Pipeline Configuration
GitHub Actions
```yaml
.github/workflows/deploy.yml
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
env:
NODE_ENV: production
API_KEY: ${{ secrets.API_KEY }}
steps:
- name: Deploy
run: |
export DATABASE_URL=${{ secrets.DATABASE_URL }}
npm run deploy
```
Jenkins Pipeline
```groovy
pipeline {
agent any
environment {
NODE_ENV = 'production'
API_KEY = credentials('api-key')
}
stages {
stage('Deploy') {
steps {
sh 'export DATABASE_URL=$DATABASE_URL && npm run deploy'
}
}
}
}
```
Database Configuration
PostgreSQL
```bash
export PGHOST=localhost
export PGPORT=5432
export PGDATABASE=myapp
export PGUSER=username
export PGPASSWORD=password
```
MySQL
```bash
export MYSQL_HOST=localhost
export MYSQL_PORT=3306
export MYSQL_DATABASE=myapp
export MYSQL_USER=username
export MYSQL_PASSWORD=password
```
Cloud Platform Configuration
AWS
```bash
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
export AWS_DEFAULT_REGION=us-west-2
export AWS_PROFILE=production
```
Google Cloud Platform
```bash
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
export GOOGLE_CLOUD_PROJECT=my-project-id
export GCLOUD_ZONE=us-central1-a
```
Advanced Techniques
Variable Substitution and Expansion
Basic Substitution
```bash
export BASE_PATH=/opt/myapp
export CONFIG_PATH=$BASE_PATH/config
export LOG_PATH=$BASE_PATH/logs
```
Default Values
```bash
Use default if variable is not set
export PORT=${PORT:-3000}
export NODE_ENV=${NODE_ENV:-development}
Use default if variable is empty or not set
export DATABASE_URL=${DATABASE_URL-postgresql://localhost:5432/myapp}
```
Conditional Assignment
```bash
Set only if not already set
: ${API_TIMEOUT:=30}
Complex conditional logic
if [ -z "$ENVIRONMENT" ]; then
export ENVIRONMENT=development
fi
```
Environment Variable Files and Management
Using direnv
Install and configure direnv for automatic environment loading:
```bash
Install direnv (Ubuntu/Debian)
sudo apt-get install direnv
Add to shell configuration
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
Create .envrc file in project directory
echo 'export NODE_ENV=development' > .envrc
echo 'export API_KEY=secret' >> .envrc
Allow direnv to load the file
direnv allow
```
Creating Environment Loading Scripts
```bash
#!/bin/bash
load-env.sh
Development environment
if [ "$1" = "dev" ]; then
export NODE_ENV=development
export DATABASE_URL=postgresql://localhost:5432/myapp_dev
export API_KEY=dev_api_key
fi
Production environment
if [ "$1" = "prod" ]; then
export NODE_ENV=production
export DATABASE_URL=postgresql://prod-server:5432/myapp
export API_KEY=prod_api_key
fi
echo "Environment loaded for $1"
```
Usage:
```bash
source load-env.sh dev
```
Environment Variable Validation
Bash Validation Script
```bash
#!/bin/bash
validate-env.sh
required_vars=("DATABASE_URL" "API_KEY" "JWT_SECRET")
for var in "${required_vars[@]}"; do
if [ -z "${!var}" ]; then
echo "Error: $var is not set"
exit 1
fi
done
echo "All required environment variables are set"
```
Python Validation
```python
import os
import sys
required_vars = ['DATABASE_URL', 'API_KEY', 'JWT_SECRET']
for var in required_vars:
if not os.getenv(var):
print(f"Error: {var} environment variable is not set")
sys.exit(1)
print("All required environment variables are set")
```
Common Issues and Troubleshooting
Variable Not Found or Empty
Symptoms
- Commands fail with "command not found"
- Applications can't find configuration values
- Variables return empty values
Solutions
```bash
Check if variable is set
echo $VARIABLE_NAME
Check all environment variables
env | grep VARIABLE_NAME
Verify export status
declare -p VARIABLE_NAME
Re-export if necessary
export VARIABLE_NAME=value
```
Changes Not Persisting
Problem
Variables disappear after closing terminal or restarting system.
Solutions
1. Ensure proper configuration file modification:
```bash
# Check which shell you're using
echo $SHELL
# Edit appropriate file
# For bash: ~/.bashrc or ~/.bash_profile
# For zsh: ~/.zshrc
nano ~/.bashrc
# Add export statements
export VARIABLE_NAME=value
# Reload configuration
source ~/.bashrc
```
2. Verify file permissions:
```bash
ls -la ~/.bashrc
chmod 644 ~/.bashrc
```
PATH Variable Issues
Symptoms
- "Command not found" errors for installed programs
- Unable to run executables from custom directories
Diagnosis and Solutions
```bash
Check current PATH
echo $PATH
Find where a command should be
which command_name
whereis command_name
Add missing directory to PATH
export PATH=$PATH:/missing/directory
Make permanent by adding to shell configuration
echo 'export PATH=$PATH:/missing/directory' >> ~/.bashrc
source ~/.bashrc
```
Windows-Specific Issues
Command Prompt vs. PowerShell Differences
```cmd
Command Prompt syntax
set VAR=value
echo %VAR%
PowerShell syntax
$env:VAR = "value"
echo $env:VAR
```
Registry Issues
If `setx` commands fail:
```cmd
Check registry entries
reg query "HKCU\Environment"
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Manually edit if necessary (advanced users only)
regedit
```
Encoding and Special Characters
Problem
Variables with spaces or special characters not working correctly.
Solutions
```bash
Use quotes for values with spaces
export MESSAGE="Hello World"
export PATH="$PATH:/path with spaces/bin"
Escape special characters
export SPECIAL_VAR="value with \$dollar and \"quotes\""
Use single quotes to prevent expansion
export LITERAL='$HOME/path'
```
Environment Variable Inheritance Issues
Problem
Child processes don't see parent environment variables.
Diagnosis
```bash
Check if variable is exported
declare -p VARIABLE_NAME
If not exported, you'll see:
declare -- VARIABLE_NAME="value"
If exported, you'll see:
declare -x VARIABLE_NAME="value"
```
Solution
```bash
Export the variable
export VARIABLE_NAME=value
Or export existing variable
VARIABLE_NAME=value
export VARIABLE_NAME
```
Best Practices and Security Considerations
Security Best Practices
Never Store Sensitive Data in Plain Text
```bash
BAD: Storing secrets in shell history
export API_KEY=secret123
GOOD: Use secure vaults or encrypted storage
AWS Secrets Manager
aws secretsmanager get-secret-value --secret-id prod/api/key
HashiCorp Vault
vault kv get -field=api_key secret/myapp
Azure Key Vault
az keyvault secret show --name api-key --vault-name myvault
```
Use Environment-Specific Configurations
```bash
Separate configurations by environment
~/.config/myapp/development.env
~/.config/myapp/production.env
~/.config/myapp/staging.env
Load appropriate configuration
case "$ENVIRONMENT" in
"production")
source ~/.config/myapp/production.env
;;
"staging")
source ~/.config/myapp/staging.env
;;
*)
source ~/.config/myapp/development.env
;;
esac
```
Validate and Sanitize Input
```bash
#!/bin/bash
Validate environment variables
validate_url() {
local url=$1
if [[ $url =~ ^https?:// ]]; then
return 0
else
echo "Invalid URL format: $url"
return 1
fi
}
if ! validate_url "$API_ENDPOINT"; then
exit 1
fi
```
Organization and Maintainability
Use Consistent Naming Conventions
```bash
Good naming conventions
export MYAPP_DATABASE_URL=postgresql://localhost:5432/myapp
export MYAPP_API_KEY=secret
export MYAPP_LOG_LEVEL=info
Group related variables
export AWS_ACCESS_KEY_ID=key
export AWS_SECRET_ACCESS_KEY=secret
export AWS_DEFAULT_REGION=us-west-2
```
Document Your Environment Variables
```bash
Create documentation file
cat > ENV_VARIABLES.md << EOF
Environment Variables
Required Variables
- \`DATABASE_URL\`: PostgreSQL connection string
- \`API_KEY\`: Third-party API authentication key
- \`JWT_SECRET\`: Secret for JWT token signing
Optional Variables
- \`LOG_LEVEL\`: Logging level (default: info)
- \`PORT\`: Application port (default: 3000)
EOF
```
Use Configuration Management Tools
Ansible Example
```yaml
playbook.yml
- name: Set environment variables
lineinfile:
path: /etc/environment
line: "{{ item.key }}={{ item.value }}"
state: present
with_items:
- { key: "NODE_ENV", value: "production" }
- { key: "DATABASE_URL", value: "{{ database_url }}" }
```
Terraform Example
```hcl
resource "aws_lambda_function" "app" {
filename = "app.zip"
function_name = "myapp"
runtime = "nodejs14.x"
environment {
variables = {
NODE_ENV = "production"
DATABASE_URL = var.database_url
API_KEY = var.api_key
}
}
}
```
Performance Considerations
Minimize Environment Variable Count
```bash
Instead of many individual variables
export DB_HOST=localhost
export DB_PORT=5432
export DB_NAME=myapp
export DB_USER=user
export DB_PASS=pass
Use a single connection string
export DATABASE_URL=postgresql://user:pass@localhost:5432/myapp
```
Use Lazy Loading for Expensive Operations
```bash
Expensive operation - only run when needed
get_database_url() {
if [ -z "$DATABASE_URL" ]; then
export DATABASE_URL=$(aws secretsmanager get-secret-value --secret-id db-url --query SecretString --output text)
fi
echo $DATABASE_URL
}
```
Cross-Platform Compatibility
Writing Portable Scripts
```bash
#!/bin/bash
portable-env.sh
Detect operating system
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
# Windows (Git Bash, MSYS2)
export PATH_SEPARATOR=";"
export HOME_DIR="$USERPROFILE"
elif [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
export PATH_SEPARATOR=":"
export HOME_DIR="$HOME"
else
# Linux and others
export PATH_SEPARATOR=":"
export HOME_DIR="$HOME"
fi
Use variables appropriately
export CUSTOM_PATH="$HOME_DIR/bin${PATH_SEPARATOR}$PATH"
```
Conclusion
Environment variables are essential tools for configuring applications, managing system behavior, and maintaining secure, flexible software deployments. This comprehensive guide has covered the fundamental concepts and advanced techniques for setting and exporting environment variables across different operating systems.
Key Takeaways
1. Understanding the Basics: Environment variables provide a standardized way to pass configuration data to applications without hardcoding values.
2. Platform Differences: While the concepts are universal, the implementation varies between Windows, macOS, and Linux systems. Understanding these differences is crucial for cross-platform development.
3. Temporary vs. Permanent: Choose the appropriate method based on whether you need variables for a single session or persistent across system restarts.
4. Export Importance: In Unix-like systems, exporting variables is essential for making them available to child processes.
5. Security Matters: Never store sensitive information in plain text environment variables in production systems. Use secure vaults and encrypted storage solutions.
Next Steps
To further enhance your environment variable management skills:
1. Explore Configuration Management: Learn tools like Ansible, Terraform, or Docker for automated environment variable deployment.
2. Implement Secret Management: Investigate cloud-based secret management services like AWS Secrets Manager, Azure Key Vault, or HashiCorp Vault.
3. Practice with Real Projects: Apply these techniques to actual development projects to gain practical experience.
4. Learn Containerization: Understand how environment variables work in Docker and Kubernetes environments.
5. Study CI/CD Integration: Explore how environment variables integrate with continuous integration and deployment pipelines.
Additional Resources
- Documentation: Consult your operating system's official documentation for the most up-to-date information.
- Community Forums: Participate in developer communities to learn from others' experiences.
- Security Guidelines: Follow industry best practices for secure configuration management.
By mastering environment variable management, you'll have a powerful tool for creating flexible, maintainable, and secure applications that can adapt to different deployment environments without code changes. Remember to always prioritize security and follow best practices when handling sensitive configuration data.