CodeToLive

Advanced Bash Scripting

Take your Bash scripting skills to the next level with these advanced techniques and patterns.

Process Management


# Run command in background
command &

# Get PID of last background command
bg_pid=$!

# Wait for background process to complete
wait $bg_pid

# Kill process by PID
kill $bg_pid

# Kill all child processes on exit
trap 'kill $(jobs -p)' EXIT
      

Parallel Execution


# Run commands in parallel
command1 &
command2 &
command3 &
wait  # Wait for all to complete

# Limit parallel processes
max_jobs=4
for item in "${items[@]}"; do
    while (( $(jobs | wc -l) >= max_jobs )); do
        sleep 0.1
    done
    process_item "$item" &
done
wait
      

Named Pipes (FIFOs)


# Create a named pipe
mkfifo mypipe

# Writer process
echo "data" > mypipe &

# Reader process
while read line; do
    echo "Received: $line"
done < mypipe

# Clean up
rm mypipe
      

Signal Handling


# Handle signals
trap 'cleanup' EXIT
trap 'echo "Interrupted!"; exit 1' INT TERM

# Ignore signals
trap '' HUP  # Ignore hangup signal

# Temporary ignore
trap '' INT
# ... critical section ...
trap - INT   # Restore default behavior
      

Advanced Parameter Expansion


# Default values
${var:-default}  # Use default if var is unset or empty
${var:=default}  # Assign default if var is unset or empty
${var:?error}    # Display error if var is unset or empty

# String manipulation
${var#pattern}   # Remove shortest prefix match
${var##pattern}  # Remove longest prefix match
${var%pattern}   # Remove shortest suffix match
${var%%pattern}  # Remove longest suffix match
${var/old/new}   # Replace first match
${var//old/new}  # Replace all matches
${var:offset}    # Substring from offset
${var:offset:length}  # Substring with length

# Array operations
${array[@]:start:length}  # Array slice
${!array[@]}     # All array indices
${#array[@]}     # Number of elements
      

Co-Processes


# Start co-process
coproc myproc {
    while read -r input; do
        echo "Processing: $input"
    done
}

# Send to co-process
echo "data" >&${myproc[1]}

# Read from co-process
read -r output <&${myproc[0]}
echo "Received: $output"
      

Advanced I/O Redirection


# Redirect both stdout and stderr to file
command >file 2>&1
command &>file

# Redirect stderr to stdout and stdout to file
command 2>&1 >file

# Tee to multiple files
command | tee file1 file2 >/dev/null

# Redirect to multiple commands
command | tee >(grep error > errors.log) >(grep warning > warnings.log) > output.log
      

Script Templates

A robust script template with common features:


#!/bin/bash

# Strict mode
set -euo pipefail

# Configuration
SCRIPT_NAME=$(basename "$0")
VERSION="1.0.0"
LOG_FILE="${SCRIPT_NAME%.*}.log"

# Help function
usage() {
    cat <&2
    elif [[ -z ${QUIET:-} ]]; then
        echo -e "$timestamp [$level] $message"
    fi
    
    echo "$timestamp [$level] $message" >> "$LOG_FILE"
}

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help) usage; exit 0 ;;
        -v|--version) echo "$SCRIPT_NAME $VERSION"; exit 0 ;;
        -d|--debug) DEBUG=1; set -x ;;
        -q|--quiet) QUIET=1 ;;
        *) break ;;
    esac
    shift
done

# Main function
main() {
    log "INFO" "Starting $SCRIPT_NAME"
    
    # Check requirements
    if ! command -v required_command &>/dev/null; then
        log "ERROR" "required_command not found"
        exit 1
    fi
    
    # Process arguments
    if [[ $# -eq 0 ]]; then
        log "ERROR" "No arguments provided"
        usage
        exit 1
    fi
    
    # Main logic here
    for arg in "$@"; do
        log "INFO" "Processing: $arg"
    done
    
    log "INFO" "Script completed successfully"
}

# Run main function
main "$@"
      

Performance Optimization

Security Considerations

Further Learning

To continue mastering Bash scripting: