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.