Bash Environment
The Bash environment consists of variables, settings, and configurations that determine how Bash behaves. Understanding and managing this environment is crucial for effective shell scripting and system administration.
Environment Variables
Environment variables are key-value pairs that affect how programs run. They’re inherited by child processes and available to all programs launched from the shell.
Viewing Environment Variables
# Display all environment variables
$ env
PATH=/usr/local/bin:/usr/bin:/bin
HOME=/home/username
USER=username
SHELL=/bin/bash
# Display specific variable
$ echo $HOME
/home/username
# Alternative method
$ printenv HOME
/home/username
# List all variables (including shell variables)
$ setCommon Environment Variables
System Variables
# User information
echo $USER # Current username
echo $HOME # User's home directory
echo $UID # User ID number
echo $GROUPS # User's group memberships
# System information
echo $HOSTNAME # System hostname
echo $HOSTTYPE # Machine type
echo $OSTYPE # Operating system type
echo $MACHTYPE # Machine description
# Shell information
echo $SHELL # Path to current shell
echo $BASH_VERSION # Bash version
echo $0 # Name of current script/shellPath Variables
# Executable search path
echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
# Library search path
echo $LD_LIBRARY_PATH
# Manual page search path
echo $MANPATHLocale Variables
# Language and locale settings
echo $LANG # Default locale
echo $LC_ALL # Override all locale settings
echo $LC_TIME # Time format locale
echo $LC_NUMERIC # Number format localeSetting Environment Variables
Temporary Variables (Current Session)
# Set variable for current session
$ export MY_VAR="Hello World"
$ echo $MY_VAR
Hello World
# Alternative syntax
$ MY_VAR="Hello World"
$ export MY_VARPermanent Variables
# Add to ~/.bashrc for user-specific variables
echo 'export MY_APP_PATH="/opt/myapp"' >> ~/.bashrc
# Add to /etc/environment for system-wide variables (Ubuntu/Debian)
echo 'MY_GLOBAL_VAR="value"' | sudo tee -a /etc/environment
# Add to /etc/profile for system-wide variables (all systems)
echo 'export GLOBAL_PATH="/usr/local/custom"' | sudo tee -a /etc/profileUnsetting Variables
# Remove environment variable
$ unset MY_VAR
$ echo $MY_VAR
# (empty output)
# Remove from environment but keep as shell variable
$ export -n MY_VARShell Variables vs Environment Variables
Shell Variables
Only available in the current shell:
# Shell variable (not exported)
$ my_shell_var="local value"
$ echo $my_shell_var
local value
# Start subshell - variable not available
$ bash
$ echo $my_shell_var
# (empty)
$ exitEnvironment Variables
Available to child processes:
# Environment variable (exported)
$ export my_env_var="global value"
$ echo $my_env_var
global value
# Start subshell - variable is available
$ bash
$ echo $my_env_var
global value
$ exitSpecial Variables
Bash provides several special variables with predefined meanings:
Positional Parameters
#!/bin/bash
# script_args.sh
echo "Script name: $0"
echo "First argument: $1"
echo "Second argument: $2"
echo "All arguments: $@"
echo "Number of arguments: $#"
echo "All arguments as single string: $*"Process Variables
#!/bin/bash
echo "Current process ID: $$"
echo "Parent process ID: $PPID"
echo "Last background process ID: $!"
echo "Exit status of last command: $?"Test Special Variables
$ ./script_args.sh hello world test
Script name: ./script_args.sh
First argument: hello
Second argument: world
All arguments: hello world test
Number of arguments: 3
All arguments as single string: hello world testConfiguration Files
Bash reads various configuration files at startup, depending on how it’s invoked:
Login Shell Files (in order)
/etc/profile- System-wide login settings~/.bash_profile- User login settings~/.bash_login- Alternative user login settings~/.profile- POSIX-compatible user settings
Non-Login Interactive Shell Files
/etc/bash.bashrc- System-wide interactive settings~/.bashrc- User interactive settings
Non-Interactive Shell Files
- Uses
$BASH_ENVif set
Logout Files
~/.bash_logout- Executed when login shell exits
Configuration File Examples
~/.bashrc
# ~/.bashrc - User interactive shell configuration
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific aliases and functions
alias ll='ls -la'
alias la='ls -A'
alias l='ls -CF'
# Custom prompt
PS1='\u@\h:\w\$ '
# Environment variables
export EDITOR=vim
export PAGER=less
# Add personal bin to PATH
if [ -d "$HOME/bin" ]; then
PATH="$HOME/bin:$PATH"
fi
# Custom functions
mkcd() {
mkdir -p "$1" && cd "$1"
}
# History settings
HISTSIZE=1000
HISTFILESIZE=2000
HISTCONTROL=ignoredups~/.bash_profile
# ~/.bash_profile - User login shell configuration
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
export PATH="$HOME/.local/bin:$PATH"
# Start SSH agent
if [ -z "$SSH_AUTH_SOCK" ]; then
eval $(ssh-agent -s)
fi
# Welcome message
echo "Welcome, $USER!"
echo "Today is $(date)"Prompt Customization
The shell prompt is controlled by the PS1 variable:
Basic Prompt Variables
# Default prompt
PS1='\u@\h:\w\$ '
# Results in: user@hostname:/current/path$
# Prompt escape sequences
\u # Username
\h # Hostname (short)
\H # Hostname (full)
\w # Current working directory
\W # Basename of current directory
\d # Date
\t # Time (24-hour)
\T # Time (12-hour)
\$ # $ for regular user, # for rootColorized Prompt
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Colorized prompt
PS1="${GREEN}\u@\h${NC}:${BLUE}\w${NC}\$ "Advanced Prompt with Git Status
# Function to show git branch
git_branch() {
git branch 2>/dev/null | grep '^*' | colrm 1 2
}
# Prompt with git branch
PS1='\u@\h:\w$(git_branch)\$ 'PATH Management
The PATH variable determines where the shell looks for executable files:
Viewing PATH
# Display PATH
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
# Display PATH in readable format
$ echo $PATH | tr ':' '\n'
/usr/local/bin
/usr/bin
/bin
/usr/local/sbin
/usr/sbin
/sbinModifying PATH
# Add directory to beginning of PATH
export PATH="/new/directory:$PATH"
# Add directory to end of PATH
export PATH="$PATH:/new/directory"
# Add multiple directories
export PATH="/dir1:/dir2:$PATH:/dir3"PATH Best Practices
# Check if directory exists before adding
if [ -d "$HOME/bin" ]; then
export PATH="$HOME/bin:$PATH"
fi
# Remove duplicate entries
PATH=$(echo "$PATH" | awk -v RS=':' -v ORS=":" '!a[$1]++{if (NR > 1) printf ORS; printf $a[$1]}')Shell Options and Settings
Set Options
# Display all set options
$ set -o
# Enable options
set -o errexit # Exit on error
set -o nounset # Exit on undefined variable
set -o pipefail # Exit on pipe failure
# Disable options
set +o errexit # Disable exit on error
# Short form
set -e # Same as set -o errexit
set -u # Same as set -o nounset
set -x # Enable debug modeShopt Options
# Display all shopt options
$ shopt
# Enable options
shopt -s extglob # Extended globbing
shopt -s globstar # Recursive globbing (**)
shopt -s nocaseglob # Case-insensitive globbing
# Disable options
shopt -u extglob # Disable extended globbingEnvironment Management Scripts
Environment Setup Script
#!/bin/bash
# setup_env.sh - Development environment setup
echo "Setting up development environment..."
# Java environment
export JAVA_HOME="/usr/lib/jvm/java-11-openjdk"
export PATH="$JAVA_HOME/bin:$PATH"
# Node.js environment
export NODE_PATH="/usr/local/lib/node_modules"
export PATH="/usr/local/node/bin:$PATH"
# Python environment
export PYTHONPATH="/usr/local/lib/python3.9/site-packages:$PYTHONPATH"
# Custom application paths
export APP_HOME="/opt/myapp"
export PATH="$APP_HOME/bin:$PATH"
# Development tools
export EDITOR=vim
export BROWSER=firefox
echo "Environment setup complete!"
echo "Java version: $(java -version 2>&1 | head -1)"
echo "Node version: $(node --version 2>/dev/null || echo 'Not installed')"
echo "Python version: $(python3 --version)"Environment Backup and Restore
#!/bin/bash
# env_backup.sh - Backup current environment
BACKUP_FILE="env_backup_$(date +%Y%m%d_%H%M%S).sh"
echo "#!/bin/bash" > "$BACKUP_FILE"
echo "# Environment backup created on $(date)" >> "$BACKUP_FILE"
echo "" >> "$BACKUP_FILE"
# Backup important variables
for var in PATH HOME USER SHELL LANG; do
echo "export $var='${!var}'" >> "$BACKUP_FILE"
done
echo "Environment backed up to $BACKUP_FILE"Debugging Environment Issues
Common Environment Problems
# Check if command is found
$ which python3
/usr/bin/python3
$ type python3
python3 is /usr/bin/python3
# Check if variable is set
$ [ -z "$JAVA_HOME" ] && echo "JAVA_HOME not set"
# Debug PATH issues
$ echo $PATH | grep -o '[^:]*' | while read dir; do
[ -d "$dir" ] || echo "Directory not found: $dir"
doneEnvironment Diagnostic Script
#!/bin/bash
# env_diagnostic.sh - Diagnose environment issues
echo "=== Environment Diagnostic ==="
echo "Date: $(date)"
echo "User: $USER"
echo "Shell: $SHELL"
echo "Bash Version: $BASH_VERSION"
echo
echo "=== PATH Analysis ==="
echo "PATH has $(echo $PATH | tr ':' '\n' | wc -l) directories"
echo $PATH | tr ':' '\n' | while read dir; do
if [ -d "$dir" ]; then
echo "✓ $dir"
else
echo "✗ $dir (not found)"
fi
done
echo
echo "=== Important Variables ==="
for var in HOME USER SHELL LANG EDITOR PAGER; do
echo "$var: ${!var:-'(not set)'}"
doneUnderstanding and properly managing the Bash environment is essential for creating robust scripts and maintaining a productive development environment. The environment affects everything from command execution to script behavior, making it a fundamental aspect of shell scripting.