def run

      # Validate - this will throw an exception if settings are not valid
      validate_settings

      # Run everything inside a lock, ensuring that only one instance of this
      # task is running.
      Lock.create(self) do

        # Find the schedule to run
        schedule = find_schedule
        unless schedule
          logger.info "No backup needed - exiting"
          return
        end

        logger.info "Starting #{schedule} backup to #{settings.remote_server}"

        # Paths and other options
        timestamp = Time.now.strftime('backup_%Y-%m-%d-T%H-%M-%S')
        current_path = File.join(settings.remote_path, 'current')
        progress_path = File.join(settings.remote_path, 'incomplete')
        complete_path = File.join(schedule_path(schedule), timestamp)
        login = "#{settings.remote_user}@#{settings.remote_server}"
        rsync_path = "#{login}:#{progress_path}"

        # Make schedule folder
        execute_ssh "mkdir --verbose --parents #{schedule_path schedule}"

        # Rsync
        Rsync.execute(logger, settings.local_path, rsync_path, {
          exclude_file: settings.exclude_file,
          link_dest: current_path,
          max_upload_speed: settings.max_upload_speed,
          max_download_speed: settings.max_download_speed
        })

        # shuffle backups around
        logger.info "Do the backup shuffle"
        execute_ssh [
          "mv --verbose            #{progress_path} #{complete_path}",
          "rm --verbose --force    #{current_path}",
          "ln --verbose --symbolic #{complete_path} #{current_path}",
        ]

        delete_old_backups schedule

        logger.info "#{schedule} backup done"
      end

    rescue Exception => exception
      logger.error exception.message
      logger.error exception.backtrace
    end
def run

      # Validate - this will throw an exception if settings are not valid
      validate_settings

      # Run everything inside a lock, ensuring that only one instance of this
      # task is running.
      Lock.create(self) do

        # Find the schedule to run
        schedule = find_schedule
        unless schedule
          logger.info "No backup needed - exiting"
          return
        end

        logger.info "Starting #{schedule} backup to #{settings.remote_server}"

        # Paths and other options
        timestamp = Time.now.strftime('backup_%Y-%m-%d-T%H-%M-%S')
        current_path = File.join(settings.remote_path, 'current')
        progress_path = File.join(settings.remote_path, 'incomplete')
        complete_path = File.join(schedule_path(schedule), timestamp)
        login = "#{settings.remote_user}@#{settings.remote_server}"
        rsync_path = "#{login}:#{progress_path}"

        # Make schedule folder
        execute_ssh "mkdir --verbose --parents #{schedule_path schedule}"

        # Rsync
        Rsync.execute(logger, settings.local_path, rsync_path, {
          exclude_file: settings.exclude_file,
          link_dest: current_path,
          max_upload_speed: settings.max_upload_speed,
          max_download_speed: settings.max_download_speed
        })

        # shuffle backups around
        logger.info "Do the backup shuffle"
        execute_ssh [
          "mv --verbose            #{progress_path} #{complete_path}",
          "rm --verbose --force    #{current_path}",
          "ln --verbose --symbolic #{complete_path} #{current_path}",
        ]

        delete_old_backups schedule

        logger.info "#{schedule} backup done"
      end

    rescue Exception => exception
      logger.error exception.message
      logger.error exception.backtrace
    end
Perform the backup