Script to Incrementally Delete old Backups

This Script Assumes a folder with daily backups exists. It incrementally deletes backups. It is configurable from command line switches and comes with a default schedule already setup.

<?php

$backup_dir          = "/home/demo/backup";
$keep_files_days     = 14;
$extension_to_delete = "tgz";
$size_to_delete      = 0;
$test                = false;
$progressive         = true;
$log                 = true;
$date                = date("YmdHis");
$log_file            = "delete_old_backups_$date.log";
$log_path            = "/var/log/backup_scripts/";


$log_string = "---------------------------------------------------------\n"
  . "Starting Delete_old_backups script\nDate $date\n\n\n";

/**
 * @var Integer number of days to keep daily backups
 */
$daily   = 7;
$weekly  = 4;
$monthly = 12;

//check for command line argument
foreach ($argv as $arg)
{
  $item = explode("=", $arg);
  switch ($item[0])
  {
    case "dir":
      $backup_dir          = $item[1];
      break;
    case "keep":
      $keep_files_days     = $item[1];
      break;
    case "extension":
      $extension_to_delete = $item[1];
      break;
    case "size":
      $size_to_delete      = $item[1];
      break;
    case "progressive":
      $progressive         = $item[1];
      break;
    case "daily":
      $daily               = $item[1];
      break;
    case "weekly":
      $weekly              = $item[1];
      break;
    case "monthly":
      $monthly             = $item[1];
      break;
    case "log":
      $log                 = $item[1];
      break;
    case "log_file":
      $log_file            = $item[1];
      break;
    case "log_path":
      $log_path            = $item[1];
      break;
    case "help":
      echo get_help();
      break;
    case "test":
      $test                = ($item[1] === "true");
      break;
  }
}

/**
 * Setting up timestamps to compare daily, weekly, monthly
 */
$daily_days          = $daily;
$weekly_days         = $weekly * 7;
$monthly_days        = $monthly * 30;
$daily_file_string   = date("YmdHis", strtotime("-$daily_days day")) . ".tgz";
$weekly_file_string  = date("YmdHis", strtotime("-$weekly_days day")) . ".tgz";
$monthly_file_string = date("YmdHis", strtotime("-$monthly_days day")) . ".tgz";
$first_month         = true;
$first_week          = true;

$weekly_position  = $weekly - 1;
$monthly_position = $monthly - 1;

$weekly_array = array();
for ($i = ($weekly - 1); $i >= 0; $i--)
{
  $week_start_date  = ($i * 7);
  $week_end_date    = ($i * 7) - 7;
  $weekly_array[$i] = array(
    "keep"           => false,
    "start_filename" => date("YmdHis", strtotime("-$week_start_date day")) . ".tgz",
    "end_filename"   => date("YmdHis", strtotime("-$week_end_date day")) . ".tgz",
  );
}

$monthly_array = array();
for ($i = ($monthly - 1); $i >= 0; $i--)
{
  $month_start_date  = ($i * 30);
  $month_end_date    = ($i * 30) - 30;
  $monthly_array[$i] = array(
    "keep"           => false,
    "start_filename" => date("YmdHis", strtotime("-$month_start_date day")) . ".tgz",
    "end_filename"   => date("YmdHis", strtotime("-$month_end_date day")) . ".tgz",
  );
}

/**
 * Listing files in directory
 */
$timestamp_to_keep = strtotime("-$keep_files_days day");
$files             = scandir($backup_dir);
$date_to_keep      = date("Ymd", $timestamp_to_keep);

foreach ($files as $file)
{
  $log_string .= "found file $file\n";
  $to_delete  = false;
  $file_path  = $backup_dir . "/" . $file;
  if (endsWith($file, ".$extension_to_delete"))
  {

    if ($progressive)
    {
      $daily_cmp = strcmp($file, $daily_file_string);
      /**
       * Backups are taken daily so we do nothing for the files less than the daily threshold
       */
      if ($daily_cmp < 0)
      {
        $weekly_cmp = strcmp($file, $weekly_file_string);

        /**
         * Checking for weekly files
         */
        if ($weekly_cmp >= 0)
        {
          if (can_delete($weekly_array, $weekly_position, $file, $first_week))
          {
            $to_delete = true;
          }
        }
        else
        {
          if (can_delete($monthly_array, $monthly_position, $file, $first_month))
          {
            $to_delete = true;
          }
        }//end monthly (else greater than 4 weeks ago)
      }
    }//end if $progressive = true
    else
    {
      //  echo "ends with $extension_to_delete\n";
      $timestamp_cmp = strcmp($file, $date_to_keep);
      //echo $timestamp_cmp . "\n";
      if (($timestamp_cmp < 0) && ($progressive == false ))
      {
        $to_delete = true;
        if ($debug){
          echo "to_delete $file\n";
        }
        //echo $file_path . "\n";
      }//end check for time and progressive == false;
    }//end else  (progressive == false)

    if ($to_delete)
    {
      $log_string .= "Deleting $file\n";
      if (!$test)
      {
        unlink($file_path);
      }
    }//end if($to_delete)
    else
    {
      $log_string .= "Keeping $file\n";
    }//end else (!$to_delete)
  }//end check for timestamp
}//end  foreach file
//var_dump($test);
$ret = file_put_contents($log_path . $log_file, $log_string, FILE_APPEND);
//var_dump($ret);
exit();

/* * ********************************************************************************** */

function can_delete(&$periods, &$period_pointer, $current_file, &$first_period)
{
  if (in_period($periods, $period_pointer, $current_file, $first_period))
  {
    if ($periods[$period_pointer]["keep"] == false)
    {
      $periods[$period_pointer]["keep"] = $current_file;
      return false;
    }
    else
    {
      return true;
    }
  }
  return true;
}

function in_period(&$periods, &$period_pointer, $current_file, &$first_period)
{
  $start_cmp = strcmp($periods["$period_pointer"]["start_filename"], $current_file);
  $end_cmp   = strcmp($periods["$period_pointer"]["end_filename"], $current_file);
  while (($end_cmp < 0) && ($period_pointer >= 0))
  {// && ($first_period === true)) {
    $period_pointer--;
    $start_cmp = strcmp($periods["$period_pointer"]["start_filename"], $current_file);
    $end_cmp   = strcmp($periods["$period_pointer"]["end_filename"], $current_file);
  }
  $first_period = false;


  if (($start_cmp < 0) && ($end_cmp >= 0))
  {
    return true;
  }
  return false;
}

function endsWith($haystack, $needle)
{
  $length = strlen($needle);
  if ($length == 0)
  {
    return true;
  }
  return (substr($haystack, -$length) === $needle);
}

function get_help()
{
  return <<<help
  Script to delete old backups.

  Options:

  help -- show this message

    dir={dir} -- Change the location of the backups

    case "progressive":

    case "daily":

    case "weekly":

    case "monthly":

    case "log":

    case "log_file":
  
    case "log_path":
help;
}

 

4 Replies to “Script to Incrementally Delete old Backups”

  1. I do not even know how I ended up here, but I thought this post was good. I don’t know who you are but definitely you are going to a famous blogger if you are not already 😉 Cheers!

Leave a Reply

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

%d bloggers like this: