π Automating MySQL Backups with Bash Script & Cron
Databases are the heart of most applicationsβand losing them can be a nightmare. Manual backups work for quick fixes, but in production environments, automated MySQL backups are essential.
In this guide, weβll build a simple Bash script to back up MySQL databases, compress them, keep them for a fixed number of days, and schedule it with cron.
π Why Automate Backups?
- β Ensures you always have a recent copy of your data
- β Reduces risk of human error
- β Saves time compared to manual exports
- β Easy to restore when disaster strikes
π Prerequisites
- A Linux server with MySQL/MariaDB installed
- A user with access to all databases you want to back up
- Basic knowledge of shell commands
1) Login as Root
sudo -i
2) Create a Backup Folder & Script File
mkdir -p /home/backup
touch /home/backup/backup-mysql.sh
nano /home/backup/backup-mysql.sh
3.1) Add the Backup Script for all Databases.
Paste this inside the file:
#!/bin/bash
#----------------------------------------
# MySQL Backup Script
#----------------------------------------
# π§ Configuration
HOST='mysql-localhost' # MySQL server host
USER='mysql-username' # Username
PASSWORD='mysql-password' # Password
DAYS_TO_KEEP=5 # Delete backups older than X days
GZIP=1 # 1 = gzip compression, 0 = plain .sql
BACKUP_PATH='/home/backup/mysql' # Location to store backups
#TIMESTAMP=$(date +"%d_%m_%Y_%H_%M_%S") # Date-time for unique file names
TIMESTAMP=$(date -d "yesterday" +"%d_%m_%Y") #Date-time for previous date file names. reminder here crontab use after 12 am
#----------------------------------------
# π Create backup folder if not exists
if [ ! -d "$BACKUP_PATH" ]; then
mkdir -p "$BACKUP_PATH"
fi
# π Get database list
databases=$(mysql -h "$HOST" -u "$USER" -p"$PASSWORD" -e "SHOW DATABASES;" | tr -d "|" | grep -v Database)
# π Loop through databases
for DB in $databases; do
# Skip system databases
if [ "$DB" = 'information_schema' ] || [ "$DB" = 'performance_schema' ] || [ "$DB" = 'mysql' ] || [ "$DB" = 'sys' ]; then
echo "Skipping database: $DB"
continue
fi
# Backup (with or without compression)
if [ "$GZIP" -eq 0 ]; then
echo "Backing up database: $DB (no compression)"
mysqldump -h "$HOST" -u "$USER" -p"$PASSWORD" --databases "$DB" --single-transaction --quick --extended-insert --compact --hex-blob --max-allowed-packet=256M --net-buffer-length=2M > "$BACKUP_PATH/${DB}-${TIMESTAMP}.sql"
else
echo "Backing up database: $DB (with compression)"
mysqldump -h "$HOST" -u "$USER" -p"$PASSWORD" --databases "$DB" --single-transaction --quick --extended-insert --compact --hex-blob --max-allowed-packet=256M --net-buffer-length=2M | gzip -9 -c > "$BACKUP_PATH/${DB}-${TIMESTAMP}.sql.gz"
fi
done
# π§Ή Delete old backups
if [ "$DAYS_TO_KEEP" -gt 0 ]; then
echo "Deleting backups older than $DAYS_TO_KEEP days"
find "$BACKUP_PATH"/* -mtime +"$DAYS_TO_KEEP" -exec rm {} \;
fi
3.2) Add the Backup Script for single Database.
Paste this inside the file:
#!/bin/bash
#----------------------------------------
# MySQL Backup Script
#----------------------------------------
# π§ Configuration
HOST='mysql-localhost' # MySQL server host
USER='mysql-username' # Username
PASSWORD='mysql-password' # Password
DB='mysql-database'
DAYS_TO_KEEP=5 # Delete backups older than X days
GZIP=1 # 1 = gzip compression, 0 = plain .sql
BACKUP_PATH='/home/backup/mysql' # Location to store backups
#TIMESTAMP=$(date +"%d_%m_%Y_%H_%M_%S") # Date-time for unique file names
TIMESTAMP=$(date -d "yesterday" +"%d_%m_%Y") #Date-time for previous date file names. reminder here crontab use after 12 am
#----------------------------------------
# Create the backup folder
if [ ! -d $BACKUP_PATH ]; then
mkdir -p $BACKUP_PATH
fi
# Backup (with or without compression)
if [ "$GZIP" -eq 0 ]; then
echo "Backing up database: $DB (no compression)"
mysqldump -h "$HOST" -u "$USER" -p"$PASSWORD" --databases "$DB" --single-transaction --quick --extended-insert --compact --hex-blob --max-allowed-packet=256M --net-buffer-length=2M > "$BACKUP_PATH/${DB}-${TIMESTAMP}.sql"
else
echo "Backing up database: $DB (with compression)"
mysqldump -h "$HOST" -u "$USER" -p"$PASSWORD" --databases "$DB" --single-transaction --quick --extended-insert --compact --hex-blob --max-allowed-packet=256M --net-buffer-length=2M | gzip -9 -c > "$BACKUP_PATH/${DB}-${TIMESTAMP}.sql.gz"
fi
# Delete old backups
if [ "$DAYS_TO_KEEP" -gt 0 ] ; then
echo "Deleting backups older than $DAYS_TO_KEEP days"
find $BACKUP_PATH/* -mtime +$DAYS_TO_KEEP -exec rm {} \;
fi
4) Make the Script Executable
chmod +x /home/backup/backup-mysql.sh
5) Test the Script
Run it manually:
/home/backup/backup-mysql.sh
Backups will be stored inside:
/home/backup/mysql/
6) Automate with Cron
Open crontab:
crontab -e
Add this line to run the backup daily at 2:30 AM:
30 2 * * * /home/backup/backup-mysql.sh >/dev/null 2>&1
Restart cron service:
sudo systemctl restart cron
π§ How It Works (Script Breakdown)
- Configuration variables β Define MySQL credentials, backup path, retention days.
-
Timestamp β Ensures unique filenames (
dbname-24_08_2025_02_30_00.sql.gz). -
Timestamp β Ensures previous filenames (
dbname-24_08_2025.sql.gz). -
Database filtering β Skips system databases (
information_schema, etc.). -
mysqldump with
--single-transactionβ Ensures consistent snapshot for InnoDB without locking tables. - gzip compression β Saves space.
-
Retention policy (
find -mtime) β Deletes backups older than 5 days.
β Conclusion
With just a few lines of Bash and a cron job, youβve automated MySQL backups.
- Backups run every day at 2:30 AM
- Old backups older than 5 days are automatically removed
- The script is simple to extend for remote storage, logging, or notifications
Automating backups is a small investment that can save you hoursβor even your entire projectβin case of data loss.
Top comments (0)