Auto Backup MySQL Database using PHP Cron (Linux & Windows)

Automatically backing up your MySQL database is critical for production websites and applications. Manual backups are error-prone and often forgotten, while automated backups ensure your data is safe even if something goes wrong.

In this tutorial, you’ll learn how to auto backup a MySQL database using PHP and Cron (Linux/macOS) or Task Scheduler (Windows). We’ll use a CLI-based PHP script that creates compressed MySQL backups, stores them in a secure folder, and automatically deletes old backups based on a retention policy.

📌 What You’ll Learn

  • How to create a MySQL backup using PHP and mysqldump
  • How to compress database backups automatically
  • How to configure backup retention (auto delete old backups)
  • How to schedule backups using Cron (Linux)
  • How to schedule backups using Task Scheduler (Windows)

🛠️ Prerequisites

  • A server with PHP installed (CLI version)
  • Access to MySQL database credentials
  • mysqldump utility installed (usually comes with MySQL)
  • CLI access (Terminal / Command Prompt)
  • Cron access (Linux/macOS) or Task Scheduler (Windows)

📁 Project Structure

Create a simple folder structure like below:

mysql-auto-backup/
│── backup.php
│── config.php
└── backups/

backup.php: The main PHP script that performs the backup.
config.php: Configuration file for database credentials and backup settings.
backups/: Directory where backups will be stored.
Make sure the backups/ directory is writable by the user running the PHP script.

⚙️ Step 1: Database Configuration (config.php)

Create a config.php file to store database credentials and backup settings in a clean and reusable way.
Key Configuration Options:

  • db_host: Database host (usually localhost or 127.0.0.1)
  • db_user: Database username
  • db_pass: Database password
  • db_name: Name of the database to back up
  • backup_dir: Directory where backups will be stored
  • retention_days: Number of days to keep backups before deletion
  • mysqldump_path: Path to the mysqldump binary
<?php 
return [
    
'db_host' => '127.0.0.1',
    
'db_user' => 'root',
    
'db_pass' => '',
    
'db_name' => 'your_database',

    
// Directory where backups will be stored
    
'backup_dir' => __DIR__ '/backups',

    
// Automatically delete backups older than X days
    
'retention_days' => 7,
    
    
// Path to mysqldump binary (use 'mysqldump' if it's on PATH or set full path on Windows)
    
'mysqldump_path' => 'mysqldump',
];
?>

🗄️ Step 2: Create Backup Script (backup.php)

Create the main backup script backup.php that will perform the database backup using the configuration from config.php. This script will:

  • Load configuration settings
  • Ensure the backup directory exists
  • Generate a filename based on the current date and time
  • Execute the mysqldump command to create a database dump
  • Compress the dump using gzip
  • Handle errors gracefully
  • Delete old backups automatically based on the retention policy
<?php 
// Load configuration
$config = require __DIR__ '/config.php';

// Ensure backup directory exists
$backupDir $config['backup_dir'];
if (!
is_dir($backupDir)) {
    if (!
mkdir($backupDir0755true)) {
        
fwrite(STDERR"Failed to create backup directory: $backupDir\n");
        exit(
2);
    }
}

// Prepare filename
$dbName $config['db_name'];
$date date('Y-m-d_H-i-s');
$filename sprintf('%s/%s_%s.sql.gz'rtrim($backupDir'/\\'), $dbName$date);

// Prepare mysqldump command
$mysqldump $config['mysqldump_path'];

// Build command without exposing password in process list on *nix where possible.
$cmdParts = [];
$cmdParts[] = escapeshellcmd($mysqldump);
$cmdParts[] = '--host=' escapeshellarg($config['db_host']);
$cmdParts[] = '--user=' escapeshellarg($config['db_user']);
// Use --password=... (mysqldump requires it) — on some systems consider using ~/.my.cnf for safety.
$cmdParts[] = '--password=' escapeshellarg($config['db_pass']);
$cmdParts[] = '--single-transaction';
$cmdParts[] = '--quick';
$cmdParts[] = escapeshellarg($dbName);
$cmd implode(' '$cmdParts);

$descriptors = [
    
=> ['pipe''w'], // stdout
    
=> ['pipe''w'], // stderr
];

// Execute mysqldump process
$process = @proc_open($cmd$descriptors$pipes);
if (!
is_resource($process)) {
    
fwrite(STDERR"Failed to start mysqldump process\n");
    exit(
3);
}

$out $pipes[1];
$err $pipes[2];

// Open gzip file for writing
$gz = @gzopen($filename'w9');
if (
$gz === false) {
    
fclose($out);
    
fclose($err);
    
proc_close($process);
    
fwrite(STDERR"Failed to open output file for writing: $filename\n");
    exit(
4);
}

// Stream dump output into gz file
while (!feof($out)) {
    
$chunk fread($out8192);
    if (
$chunk === false) break;
    if (
$chunk !== ''gzwrite($gz$chunk);
}

// Capture any stderr output
$stderrOutput stream_get_contents($err);
fclose($out);
fclose($err);

// Close process and gzip file
$exitCode proc_close($process);
gzclose($gz);

// Check for errors
if ($exitCode !== 0) {
    @
unlink($filename);
    
fwrite(STDERR"mysqldump failed (code $exitCode): $stderrOutput\n");
    exit(
$exitCode);
}

echo 
"Backup created: $filename\n";

// Rotate old backups
$retention = (int)$config['retention_days'];
if (
$retention 0) {
    
$pattern rtrim($backupDir'/\\') . '/' $dbName '_*.sql.gz';
    foreach (
glob($pattern) as $file) {
        if (
filemtime($file) < time() - ($retention 86400)) {
            @
unlink($file);
        }
    }
}

exit(
0);
?>

🕒 Step 3: Test Backup Script Manually

Before scheduling the backup script, it’s important to test it manually to ensure it works as expected.

  1. Open your terminal or command prompt.
  2. Navigate to the project directory where backup.php is located.
  3. Run the script using the PHP CLI:
    php backup.php

    If everything is configured correctly, you’ll see:

    Backup created: /path/to/your/project/backups/your_database_YYYY-MM-DD_HH-MM-SS.sql.gz
  4. Check the backups/ directory to verify that a new backup file has been created.
  5. Review any output messages for errors or confirmations.

⏰ Step 4: Schedule Auto Backups

Now that you have the backup script ready, you need to schedule it to run automatically at regular intervals.

Scheduling on Linux/macOS using Cron:

  1. Open your terminal.
  2. Edit your crontab file by running:
    crontab -e
  3. Add a new line to schedule the backup script. For example, to run the backup every day at 2 AM, add:
    0 2 * * * /usr/bin/php /path/to/your/project/backup.php

    Make sure to replace /usr/bin/php with the path to your PHP executable and /path/to/your/project/backup.php with the actual path to your script.

  4. Save and exit the crontab editor.
  5. Your backups will now run automatically at the scheduled time.

Cron Timing Format:

* * * * *
│ │ │ │ │
│ │ │ │ └── Day of week
│ │ │ └──── Month
│ │ └────── Day of month
│ └──────── Hour
└────────── Minute

Scheduling on Windows using Task Scheduler:

  1. Open Task Scheduler from the Start menu.
  2. Click on Create Basic Task… in the Actions pane.
  3. Follow the wizard to name your task and set the trigger (e.g., daily at 2 AM).
  4. For the action, select Start a program.
  5. In the “Program/script” field, enter the path to your PHP executable (e.g., C:\path\to\php.exe).
  6. In the “Add arguments (optional)” field, enter the path to your backup.php script (e.g., C:\path\to\your\project\backup.php).
  7. Finish the wizard to create the task.
  8. Your backups will now run automatically at the scheduled time.

🔐 Security Best Practices

  • Store backups outside the public web directory
  • Restrict folder access using .htaccess
  • Use a dedicated MySQL user with read-only access
  • Rotate backups regularly using retention policy
  • Optionally upload backups to cloud storage (S3, Google Drive)

✅ Final Thoughts

Automating MySQL backups using PHP and Cron is a simple yet powerful solution for protecting your application data. With compression, retention cleanup, and proper scheduling, this script is production-ready and easy to maintain.

You can safely run this script on shared hosting, VPS, or dedicated servers with minimal configuration.

Here are some additional enhancements you might consider:

  • Encrypt backups for added security
  • Send email notifications on backup success/failure
  • Integrate with cloud storage APIs for offsite backups (AWS S3 / Google Drive)
  • Multiple database support
  • Implement logging in database for backup operations

Happy coding and stay backed up! 🚀

Looking for expert assistance to implement or extend this script’s functionality? Submit a Service Request

Leave a reply

construction Need this implemented in your project? Request Implementation Help → keyboard_double_arrow_up