Bash global variables
The most reliable and recommended way to share global variables across multiple Bash scripts is to
store them in a dedicated environment file and load them using the source (or .) command.
Because child processes in Linux cannot alter the environment of a parent process, standard execution will isolate variables. Sourcing executes the file within the current shell context, instantly importing all properties.
Step 1: Create the Environment File
Store your variables in a separate configuration or library file (e.g., config.env or globals.sh).
- Use lowercase or mixed-case for custom globals to avoid overwriting internal system variables like
PATHorUSER. - Use the
exportkeyword if child scripts or binaries executed by the main script also need access.
# config.env
# Custom shared variables
app_version="2.4.1"
database_url="localhost:5432"
log_directory="/var/log/myapp"
export app_version database_url log_directory
Step 2: Retrieve Variables in Your Scripts
To import these variables into any script, find the directory of the executing script and source the file safely.
#!/bin/bash
# Safely locate the directory where this script lives
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
# Load the global variables
if [ -f "$script_dir/config.env" ]; then
source "$script_dir/config.env"
else
echo "Error: config.env file not found!" >&2
exit 1
fi
# Use the variables
echo "Starting Application Version: $app_version"
echo "Connecting to Database at: $database_url"
Best Practices for Global Variables
- Use Unique Prefixes: Prepend a unique short prefix (e.g.,
cfg_version,cfg_db_url) to your shared variables to prevent naming collisions with local script variables. - Make Variables Read-Only: If the values are meant to be constants, define them with
declare -r(e.g.,declare -r app_version="2.4.1") so they cannot be accidentally overwritten. - Quote Every Expansion: Always wrap variables in double quotes when referencing them (e.g.,
"$log_directory") to ensure the shell handles spaces and special characters perfectly.
Update global variables
Here is how to dynamically update variables inside your configuration file and manage different environments (like development and production).
1. How to Dynamically Update and Save Variables
Because Bash cannot directly "save" its memory back to a file, you must use a stream editor like sed to rewrite the values inside the config.env file.
#!/bin/bash
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE}")" &> /dev/null && pwd)
config_file="$script_dir/config.env"
# Function to safely update a variable in the file
update_env_var() {
local var_name="$1"
local new_value="$2"
# Check if the variable already exists in the file
if grep -q "^${var_name}=" "$config_file"; then
# Replace the existing line
sed -i "s|^${var_name}=.*|${var_name}=\"${new_value}\"|" "$config_file"
else
# Append the new variable if it does not exist
echo "${var_name}=\"${new_value}\"" >> "$config_file"
fi
}
# Example usage: Incrementing a version number
source "$config_file"
new_version="2.4.2"
update_env_var "app_version" "$new_version"
echo "Updated app_version to $new_version inside config.env"
2. Managing Multiple Environments (Dev vs. Prod)
The cleanest approach is to create separate files for each environment and use a single master variable (APP_ENV) to load the correct one.
Step A: Create your environment files
Create specific files side-by-side in your project directory:
# dev.env
database_url="localhost:5432"
log_level="DEBUG"
# prod.env
database_url="10.0.1.50:5432"
log_level="ERROR"
Step B: Load them dynamically in your main script
Use an internal system environment variable or a default fallback to swap configuration profiles instantly:
#!/bin/bash
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE}")" &> /dev/null && pwd)
# Default to 'dev' if the APP_ENV environment variable is not set
env="${APP_ENV:-dev}"
env_file="$script_dir/${env}.env"
# Load the selected environment
if [ -f "$env_file" ]; then
source "$env_file"
echo "Loaded configuration for environment: $env"
else
echo "Error: Configuration file for '$env' not found at $env_file" >&2
exit 1
fi
# Run your logic using the environment-specific data
echo "Connecting to: $database_url"
Step C: Run the script
You can now toggle environments on the fly right from your terminal command line:
- Run in Dev:
APP_ENV=dev ./myscript.sh - Run in Prod:
APP_ENV=prod ./myscript.sh
Would you like help writing a validation function to ensure vital variables are present before your script runs, or do you want to see how to securely encrypt sensitive production passwords within these files?
Validating Required Variables
Before running core logic, you should validate that required variables are not empty. This script loops through a list of required variable names, checks if they are set, and terminates safely if any are missing.
#!/bin/bash
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE}")" &> /dev/null && pwd)
source "$script_dir/prod.env"
# Function to validate required variables
validate_env_vars() {
local missing_vars=0
# Pass the names of the variables as strings to check them
local required_vars=("database_url" "log_level" "db_password")
for var_name in "${required_vars[@]}"; do
# Indirect expansion: checks the value of the variable named by $var_name
if [ -z "${!var_name}" ]; then
echo "Error: Required variable '$var_name' is missing or empty." >&2
missing_vars=$((missing_vars + 1))
fi
done
if [ $missing_vars -gt 0 ]; then
echo "Environment validation failed with $missing_vars error(s). Exiting." >&2
exit 1
fi
}
# Run the validation
validate_env_vars
Encrypting Sensitive Production Passwords
Storing plaintext passwords in .env files is a major security risk. You can use openssl to securely encrypt your secrets, storing only the encrypted file in your repository.
Step A: Encrypt the file (One-time setup)
Run this command manually in your terminal to encrypt your sensitive production file. It will prompt you to create a decryption password (passphrase):
openssl aes-256-cbc -salt -pbkdf2 -in prod.env -out prod.env.enc
prod.env: Your original plaintext file (delete or add to.gitignoreafter encryption).prod.env.enc: The secure, encrypted file you can safely store.
Step B: Decrypt on the fly inside the script
Instead of saving the decrypted file to the hard drive (which leaks secrets), decrypt the file directly into memory and source it via a file descriptor.
#!/bin/bash
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE}")" &> /dev/null && pwd)
encrypted_file="$script_dir/prod.env.enc"
# Prompt the user or system for the decryption key securely
read -s -p "Enter environment decryption passphrase: " secret_key
echo "" # Print a newline after hidden input
if [ -f "$encrypted_file" ]; then
# Decrypt directly into memory using a bash process substitution
source <(openssl aes-256-cbc -d -salt -pbkdf2 -pass pass:"$secret_key" -in "$encrypted_file" 2>/dev/null)
if [ $? -ne 0 ]; then
echo "Error: Decryption failed. Incorrect passphrase." >&2
exit 1
fi
else
echo "Error: Encrypted environment file not found." >&2
exit 1
fi
# The variables are now available safely in memory without touching the disk
echo "Securely loaded database: $database_url"
To make this completely hands-free for automation or CI/CD pipelines, you can replace the read -s command and pass the secret passphrase through a secure host system environment variable instead.