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
- Configuration:
- Configurable backup location, directories to backup, and retention period
- Excludes common unnecessary files (*.tmp, *.swp, etc.)
- Supports different compression types (gzip, bzip2, xz)
- Safety features:
- Checks for root privileges
- Verifies available disk space
- Includes error handling and logging
- Creates detailed logs with timestamps
- 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.