Bash Script To Automate Linux Directories Backups

Performing regular backups of your files in Linux operating systems is a critical part of personal data security and overall system administration best-practice. Whether you are in charge of your personal laptop, managing development or production environment servers, creating regular backups gives you peace of mind knowing that your critical data is safe from unforeseen system disasters such as disk failures, malware attacks, or accidental deletions.

In this tutorial, we’ll walk you through the creation of a simple but powerful bash script that can be used to automate backing up of important directories in a Linux machine. The script will provide few configuration variables such as backup destination, directories to backup, required disk space for backup, date format, compression flag, and backup retention period. It’s an easy to use script and can be scheduled using cron to run at specified time interval.

Create backup bash script in Linux

Create a script in /root or your home user directory.

sudo su -
vim /root/system_backups.sh

Paste the following script content into the file you’ve created. You can also copy from the git repository.

#!/bin/bash

# =====================================================================
# Linux System Backup Script
# =====================================================================
# Description: This script creates a backup of important system directories,
#              compresses them using tar, and includes timestamps
#              for easy identification.
# Usage: ./system_backups.sh [config_file]
# Author: Josphat Mutai, https://cloudspinx.com
# Date: 2025-05-15
# =====================================================================

# =====================================================================
# CONFIGURATION
# =====================================================================
# Default configuration (can be overridden by config file)
BACKUP_DIR="/backup"                        # Where backups are stored
DIRECTORIES_TO_BACKUP=("/etc" "/home" "/root" "/var/log" "/opt")  # Directories to backup
EXCLUDE_PATTERNS=("*.tmp" "*.swp" "/home/*/Downloads" "/home/*/Trash")  # Patterns to exclude
RETENTION_DAYS=30                           # How many days to keep backups
LOG_FILE="/var/log/system_backup.log"       # Log file location
DATE_FORMAT="%Y-%m-%d_%H-%M-%S"             # Format for date in backup name
COMPRESSION_TYPE="gzip"                     # Options: gzip, bzip2, xz
REQUIRED_SPACE_GB=1                         # Required free space in GB

# =====================================================================
# FUNCTIONS
# =====================================================================

# Function to write log messages
log() {
    local level="$1"
    local message="$2"
    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
    
    # Echo to console with color
    case "$level" in
        "INFO")
            echo -e "\e[32m[INFO]\e[0m $message"  # Green
            ;;
        "WARNING")
            echo -e "\e[33m[WARNING]\e[0m $message"  # Yellow
            ;;
        "ERROR")
            echo -e "\e[31m[ERROR]\e[0m $message"  # Red
            ;;
        *)
            echo -e "[${level}] $message"
            ;;
    esac
    
    # Append to log file
    if [ -w "$(dirname "$LOG_FILE")" ]; then
        echo "[$timestamp] [${level}] $message" >> "$LOG_FILE"
    else
        echo -e "\e[31m[ERROR]\e[0m Cannot write to log file $LOG_FILE" >&2
    fi
}

# Function to load configuration from file
load_config() {
    local config_file="$1"
    if [ -f "$config_file" ]; then
        log "INFO" "Loading configuration from $config_file"
        source "$config_file"
    else
        log "WARNING" "Configuration file $config_file not found. Using defaults."
    fi
}

# Function to check for root privileges
check_root() {
    if [ "$(id -u)" -ne 0 ]; then
        log "ERROR" "This script must be run as root to properly backup system files"
        exit 1
    fi
}

# Function to check available disk space
check_disk_space() {
    # Convert GB to KB (1GB = 1048576KB)
    local required_space_kb=$((REQUIRED_SPACE_GB * 1048576))
    local available_space=$(df -k "$BACKUP_DIR" | awk 'NR==2 {print $4}')
    local available_space_gb=$(echo "scale=2; $available_space / 1048576" | bc)
    
    if [ "$available_space" -lt "$required_space_kb" ]; then
        log "ERROR" "Not enough disk space. Required: ${REQUIRED_SPACE_GB}GB, Available: ${available_space_gb}GB"
        exit 1
    else
        log "INFO" "Sufficient disk space available: ${available_space_gb}GB"
    fi
}

# Function to create backup directory if it doesn't exist
create_backup_dir() {
    if [ ! -d "$BACKUP_DIR" ]; then
        log "INFO" "Creating backup directory: $BACKUP_DIR"
        mkdir -p "$BACKUP_DIR"
        
        if [ $? -ne 0 ]; then
            log "ERROR" "Failed to create backup directory: $BACKUP_DIR"
            exit 1
        fi
    fi
}

# Function to create the backup
create_backup() {
    local timestamp=$(date +"$DATE_FORMAT")
    local hostname=$(hostname)
    local backup_file="${BACKUP_DIR}/system_backup_${hostname}_${timestamp}.tar"
    local exclude_args=""
    
    # Build exclude arguments
    for pattern in "${EXCLUDE_PATTERNS[@]}"; do
        exclude_args="$exclude_args --exclude='$pattern'"
    done
    
    # Add appropriate compression extension and option
    case "$COMPRESSION_TYPE" in
        "gzip")
            backup_file="${backup_file}.gz"
            compression_opt="-z"
            ;;
        "bzip2")
            backup_file="${backup_file}.bz2"
            compression_opt="-j"
            ;;
        "xz")
            backup_file="${backup_file}.xz"
            compression_opt="-J"
            ;;
        *)
            backup_file="${backup_file}.gz"
            compression_opt="-z"
            ;;
    esac
    
    log "INFO" "Starting backup to $backup_file"
    log "INFO" "Backing up: ${DIRECTORIES_TO_BACKUP[*]}"
    
    # Create the backup command
    # We use eval because we need to expand the exclude_args array
    backup_cmd="tar $compression_opt -cvf \"$backup_file\" $exclude_args ${DIRECTORIES_TO_BACKUP[*]} 2>/tmp/backup_errors.log"
    
    log "INFO" "Executing: $backup_cmd"
    
    # Execute backup command
    eval $backup_cmd
    
    # Check for errors
    if [ $? -eq 0 ]; then
        log "INFO" "Backup completed successfully: $backup_file"
        log "INFO" "Backup size: $(du -h "$backup_file" | cut -f1)"
        
        # Store list of backed up files
        log "INFO" "Creating file list..."
        tar -tvf "$backup_file" > "${backup_file%.tar.*}.file_list.txt" 2>/dev/null
    else
        log "ERROR" "Backup failed! Check /tmp/backup_errors.log for details"
        
        if [ -f "/tmp/backup_errors.log" ]; then
            log "ERROR" "Errors during backup: $(cat /tmp/backup_errors.log)"
        fi
        
        exit 1
    fi
}

# Function to delete old backups
clean_old_backups() {
    if [ "$RETENTION_DAYS" -gt 0 ]; then
        log "INFO" "Cleaning backups older than $RETENTION_DAYS days"
        find "$BACKUP_DIR" -name "system_backup_*.tar.*" -mtime +$RETENTION_DAYS -delete
        
        if [ $? -eq 0 ]; then
            log "INFO" "Old backups cleaned successfully"
        else
            log "WARNING" "Failed to clean old backups"
        fi
    else
        log "INFO" "Backup retention disabled"
    fi
}

# =====================================================================
# MAIN SCRIPT
# =====================================================================

# Load configuration from file if provided
if [ $# -gt 0 ]; then
    load_config "$1"
fi

# Check if running as root
check_root

# Begin backup process
log "INFO" "=== BACKUP STARTED ==="

# Create backup directory if it doesn't exist
create_backup_dir

# Check available disk space
check_disk_space

# Create the backup
create_backup

# Clean old backups
clean_old_backups

log "INFO" "=== BACKUP COMPLETED ==="

exit 0

Script explanation

  1. Configuration:
  • Configurable backup location, directories to backup, and retention period
  • Excludes common unnecessary files (*.tmp, *.swp, etc.)
  • Supports different compression types (gzip, bzip2, xz)
  1. Safety features:
  • Checks for root privileges
  • Verifies available disk space
  • Includes error handling and logging
  • Creates detailed logs with timestamps
  1. Backup features:
  • Timestamps in backup names
  • Configurable compression options
  • Creates a list of backed-up files
  • Automatic cleanup of old backups

Using script to backup directories in Linux

Make the script executable:

chmod +x system_backups.sh

Edit the key variables to customize:

BACKUP_DIR="/backup"                                                    # Where backups are stored
DIRECTORIES_TO_BACKUP=("/etc" "/home" "/root" "/var/log" "/opt")        # Directories to backup
EXCLUDE_PATTERNS=("*.tmp" "*.swp" "/home/*/Downloads" "/home/*/Trash")  # Patterns to exclude
RETENTION_DAYS=14                                                       # How many days to keep backups
COMPRESSION_TYPE="gzip"                                                 # Options: gzip, bzip2, xz
REQUIRED_SPACE_GB=10                                                    # Required free space in GB

After the changes, run the script to initiate backup:

/root/system_backups.sh

It will perform necessary checks before execution:

[INFO] === BACKUP STARTED ===
[INFO] Creating backup directory: /backup
[INFO] Sufficient disk space available: 43.77GB
[INFO] Starting backup to /backup/system_backup_ubuntu01.cloudspinx.com_2025-05-15_00-46-13.tar.gz
[INFO] Backing up: /etc /home /root /var/log /opt
[INFO] Executing: tar -z -cvf "/backup/system_backup_ubuntu01.cloudspinx.com_2025-05-15_00-46-13.tar.gz"  --exclude='*.tmp' --exclude='*.swp' --exclude='/home/*/Downloads' --exclude='/home/*/Trash' /etc /home /root /var/log /opt 2>/tmp/backup_errors.log

If the backup completes successfully without any errors, you will see the following confirmation message at the end.

[INFO] Backup completed successfully: /backup/system_backup_ubuntu01.cloudspinx.com_2025-05-15_00-46-13.tar.gz
[INFO] Backup size: 147M
[INFO] Creating file list...
[INFO] Cleaning backups older than 14 days
[INFO] Old backups cleaned successfully
[INFO] === BACKUP COMPLETED ===

List contents in the backup directory

# ls -lh /backup/
total 147M
-rw-r--r-- 1 root root 169K May 15 00:46 system_backup_ubuntu01.cloudspinx.com_2025-05-15_00-46-13.file_list.txt
-rw-r--r-- 1 root root 147M May 15 00:46 system_backup_ubuntu01.cloudspinx.com_2025-05-15_00-46-13.tar.gz

To restore files from backup, copy to destination machine and extract using tar

tar xvf <file/path>

Schedule backups using cron

Automated backups can be achieve by configuring Linux cron job. Use crontab.guru to generate your desired schedule. Once generated, use crontab -e to configure it.

sudo crontab -e

The following example runs the backup every day at 1 AM:

0 1 * * * /root/system_backups.sh

This will execute the backup script daily at 1:00 AM. Make sure the script has executable permissions.

Additional Tips

  • Use full paths in your backup script to avoid path-related errors in cron job executions.
  • Store backups offsite consider syncing the backups to remote servers, cloud storage (e.g., S3, Google Drive), or using rsync to another machine.
  • Test your backups regularly – run restore operations periodically from backups to ensure they work when needed.
  • Always exclude unnecessary files like /proc, /sys, cache directories, and large temp files to reduce size and time.

Join our Linux and open source community. Subscribe to our newsletter for tips, tricks, and collaboration opportunities!

Recent Post

Unlock the Right Solutions with Confidence

At CloudSpinx, we don’t just offer services - we deliver clarity, direction, and results. Whether you're navigating cloud adoption, scaling infrastructure, or solving DevOps challenges, our seasoned experts help you make smart, strategic decisions with total confidence. Let us turn complexity into opportunity and bring your vision to life.

Leave a Comment

Your email address will not be published. Required fields are marked *

Related Post

In this short guide we will show you how to make a snake game for playing in your terminal using […]

The Linux tablets have gained popularity over the past few years. Linux tablets are known to be secure, robust, and […]

Julia is a high-performance, high-level technical computing language that has a syntax that is familiar to users of technical computing […]

Let's Connect

Unleash the full potential of your business with CloudSpinx. Our expert solutions specialists are standing by to answer your questions and tailor a plan that perfectly aligns with your unique needs.
You will get a response from our solutions specialist within 12 hours
We understand emergencies can be stressful. For immediate assistance, chat with us now

Contact CloudSpinx today!

Download CloudSpinx Profile

Discover the full spectrum of our expertise and services by downloading our detailed Company Profile. Simply enter your first name, last name, and email address.