14.4. Startup Files#
14.4.1. Common Pitfalls#
1. Startup file loops
# Bad: bashrc sources profile which sources bashrc (infinite loop)
# ~/.bashrc
source ~/.bash_profile
# ~/.bash_profile
source ~/.bashrc
# Good: Prevent re-sourcing
if [[ -n "$BASHRC_SOURCED" ]]; then
return
fi
export BASHRC_SOURCED=1
2. Aliases don’t work in scripts
# Bad: Aliases not expanded in non-interactive shells
#!/bin/bash
alias ll='ls -lah'
ll # Does not work (alias not expanded)
# Good: Use function or full command
#!/bin/bash
ll() { ls -lah "$@"; }
ll # Works
3. Aliases with arguments fail
# Bad: Can't pass arguments to alias
alias backup='tar -czf backup.tar.gz'
backup mydir # Doesn't work as expected
# Good: Use function
backup() {
tar -czf backup.tar.gz "$@"
}
backup mydir # Works correctly
4. PATH issues from startup files
# Bad: Appending to PATH repeatedly
export PATH="$HOME/bin:$PATH" # Added every time
# Good: Check if already added
if [[ ":$PATH:" != *":$HOME/bin:"* ]]; then
export PATH="$HOME/bin:$PATH"
fi
5. Startup file doesn’t exist for scripts
# Scripts don't source ~/.bashrc by default
# Need to explicitly source for environment
#!/bin/bash
source ~/.bashrc # Load environment
# Or use bash -i for interactive shell
bash -i -c 'command'
14.4.2. Aliases and Functions#
Aliases and functions enhance productivity and provide shortcuts for common operations.
14.4.2.1. Creating and Managing Aliases#
#!/bin/bash
# Simple aliases
alias ll='ls -lah'
alias la='ls -A'
alias l='ls -CF'
alias cd..='cd ..'
alias ...='cd ../..'
# Aliases with arguments (use functions instead)
# Bad: alias grep_error='grep -i "error"' # Can't pass args easily
# Good: Use function
grep_error() {
grep -i "error" "$@"
}
# Conditional aliases
if [[ "$OSTYPE" == "darwin"* ]]; then
alias ls='ls -G' # macOS
else
alias ls='ls --color=auto' # Linux
fi
# Check alias
alias ll # Show definition
type ll # Show type (builtin, alias, function, etc.)
# Remove alias
unalias ll
# List all aliases
alias
alias | grep cd
# Safe rm (with confirmation)
alias rm='rm -i'
# Grep with useful defaults
alias grep='grep --color=auto -n'
# View large files without loading entirely
alias large_view='less +F'
14.4.2.2. Functions vs Aliases#
#!/bin/bash
# Simple alias (no arguments)
alias gst='git status'
gst # Works
# Problem: Can't use arguments with alias easily
alias grep_logs='grep "ERROR"'
grep_logs file.txt # Works, appends to command
# Solution: Use function
grep_logs() {
grep "ERROR" "$@"
}
grep_logs file.txt # Works better
# Functions with multiple operations
backup_db() {
local db=$1
local dest=${2:-.}
echo "Backing up database: $db"
mysqldump "$db" > "$dest/${db}-$(date +%Y%m%d).sql"
if [[ $? -eq 0 ]]; then
echo "✓ Backup successful"
else
echo "✗ Backup failed" >&2
return 1
fi
}
backup_db myapp /backups/
# Function with conditional logic
dstat() {
local target="${1:-.}"
if [[ ! -d "$target" ]]; then
echo "Error: $target is not a directory" >&2
return 1
fi
du -sh "$target"
}
14.4.2.3. Advanced Alias Patterns#
#!/bin/bash
# Directory navigation aliases
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
# Git shortcuts
alias gs='git status'
alias ga='git add'
alias gc='git commit'
alias gp='git push'
alias gl='git log --oneline -10'
# System monitoring
alias myip='curl ifconfig.me'
alias ports='netstat -tulanp | grep LISTEN'
alias mem='free -h'
alias disk='df -h | grep -v tmpfs'
# Safety aliases
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias ln='ln -i'
# Color output
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
# Docker shortcuts
alias docker-stop-all='docker stop $(docker ps -q)'
alias docker-rm-all='docker rm $(docker ps -aq)'
# Make aliases persist in functions
enable_aliases_in_functions() {
shopt -s expand_aliases
}
14.4.3. Shell Startup Files and Initialization#
Understanding startup files is crucial for environment customization and debugging shell behavior.
14.4.3.1. Startup File Hierarchy#
# LOGIN SHELL EXECUTION ORDER:
# 1. /etc/profile (system-wide login shell setup)
# 2. ~/.bash_profile (user login shell setup)
# 3. ~/.bash_login (alternative if .bash_profile missing)
# 4. ~/.profile (fallback if bash_profile/bash_login missing)
# INTERACTIVE NON-LOGIN SHELL:
# 1. /etc/bash.bashrc (system-wide setup)
# 2. ~/.bashrc (user interactive setup)
# NON-INTERACTIVE SHELL (scripts):
# 1. Only processes file specified by BASH_ENV variable
# 2. No startup files normally sourced
# Check what type of shell you're in
if [[ -o login ]]; then
echo "Login shell"
fi
if [[ $- == *i* ]]; then
echo "Interactive shell"
fi
14.4.3.2. Practical Startup File Configuration#
#!/bin/bash
# ~/.bashrc - User interactive shell startup
# Avoid running twice in chains
if [[ -n "$BASHRC_SOURCED" ]]; then
return
fi
export BASHRC_SOURCED=1
# Source system bashrc if available
[[ -f /etc/bashrc ]] && source /etc/bashrc
# Set environment variables
export PATH="$HOME/bin:$HOME/.local/bin:$PATH"
export EDITOR=vim
export HISTSIZE=10000
export HISTFILESIZE=20000
export HISTCONTROL=ignoredups:ignorespace
# Shell options
shopt -s histappend
shopt -s checkwinsize
shopt -s cdspell
# Aliases
alias ll='ls -lah'
alias grep='grep --color=auto'
alias df='df -h'
# Functions
mkcd() {
mkdir -p "$1" && cd "$1"
}
# Prompt customization
PS1='\u@\h:\W\$ '
# Load local environment if exists
[[ -f ~/.bashrc.local ]] && source ~/.bashrc.local
14.4.3.3. Environment Variables and Exports#
#!/bin/bash
# Set and export environment variables
export MY_APP_HOME="/opt/myapp"
export MY_APP_CONFIG="$MY_APP_HOME/config"
export MY_APP_LOG="$MY_APP_HOME/logs"
# Application-specific PATH
export PATH="$MY_APP_HOME/bin:$PATH"
# Development environment
export JAVA_HOME="/usr/lib/jvm/java-11"
export MAVEN_HOME="/opt/maven"
export PATH="$MAVEN_HOME/bin:$PATH"
# Prompt with status
export PROMPT_COMMAND='echo -ne "\033]0;$(whoami)@$(hostname):$(pwd)\007"'
# History configuration
shopt -s histappend
export PROMPT_COMMAND="$PROMPT_COMMAND; history -a; history -n"
# Colors for ls
if [[ -x /usr/bin/dircolors ]]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || \
eval "$(dircolors -b)"
alias ls='ls --color=auto'
fi