2014-03-06 03:53:13 +03:00
|
|
|
#!/usr/bin/perl
|
2014-03-30 01:16:08 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# pg_backrest.pl - Simple Postgres Backup and Restore
|
|
|
|
####################################################################################################################################
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-03-30 01:16:08 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# Perl includes
|
|
|
|
####################################################################################################################################
|
2014-07-28 01:13:23 +03:00
|
|
|
use threads;
|
2014-03-06 03:53:13 +03:00
|
|
|
use strict;
|
|
|
|
use warnings;
|
2014-07-28 01:13:23 +03:00
|
|
|
use Carp;
|
2014-03-06 03:53:13 +03:00
|
|
|
|
|
|
|
use File::Basename;
|
|
|
|
use Getopt::Long;
|
2014-08-15 17:48:50 +03:00
|
|
|
use Pod::Usage;
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-09-14 22:55:27 +03:00
|
|
|
use lib dirname($0) . '/../lib';
|
2014-06-22 17:30:17 +03:00
|
|
|
use BackRest::Utility;
|
2014-12-16 00:20:42 +02:00
|
|
|
use BackRest::Config;
|
2014-06-22 17:30:17 +03:00
|
|
|
use BackRest::File;
|
|
|
|
use BackRest::Backup;
|
|
|
|
use BackRest::Db;
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-08-15 17:48:50 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# Usage
|
|
|
|
####################################################################################################################################
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
pg_backrest.pl - Simple Postgres Backup and Restore
|
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
pg_backrest.pl [options] [operation]
|
|
|
|
|
|
|
|
Operation:
|
|
|
|
archive-get retrieve an archive file from backup
|
|
|
|
archive-push push an archive file to backup
|
|
|
|
backup backup a cluster
|
|
|
|
expire expire old backups (automatically run after backup)
|
|
|
|
|
|
|
|
General Options:
|
|
|
|
--stanza stanza (cluster) to operate on (currently required for all operations)
|
|
|
|
--config alternate path for pg_backrest.conf (defaults to /etc/pg_backrest.conf)
|
|
|
|
--version display version and exit
|
|
|
|
--help display usage and exit
|
|
|
|
|
|
|
|
Backup Options:
|
|
|
|
--type type of backup to perform (full, diff, incr)
|
2014-09-20 00:51:51 +03:00
|
|
|
--no-start-stop do not call pg_start/stop_backup(). Postmaster should not be running.
|
|
|
|
--force force backup when --no-start-stop passed and postmaster.pid exists.
|
|
|
|
Use with extreme caution as this will produce an inconsistent backup!
|
2014-08-15 17:48:50 +03:00
|
|
|
=cut
|
|
|
|
|
2014-03-30 01:16:08 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# Operation constants - basic operations that are allowed in backrest
|
|
|
|
####################################################################################################################################
|
2014-03-06 03:53:13 +03:00
|
|
|
use constant
|
|
|
|
{
|
2014-09-14 22:55:27 +03:00
|
|
|
OP_ARCHIVE_GET => 'archive-get',
|
|
|
|
OP_ARCHIVE_PUSH => 'archive-push',
|
|
|
|
OP_BACKUP => 'backup',
|
|
|
|
OP_EXPIRE => 'expire'
|
2014-03-06 03:53:13 +03:00
|
|
|
};
|
|
|
|
|
2014-03-30 01:16:08 +03:00
|
|
|
####################################################################################################################################
|
2014-03-06 03:53:13 +03:00
|
|
|
# Command line parameters
|
2014-03-30 01:16:08 +03:00
|
|
|
####################################################################################################################################
|
2014-09-20 00:51:51 +03:00
|
|
|
my $strConfigFile; # Configuration file
|
|
|
|
my $strStanza; # Stanza in the configuration file to load
|
2014-10-14 15:27:50 +03:00
|
|
|
my $strType; # Type of backup: full, diff (differential), incr (incremental)
|
2014-09-20 00:51:51 +03:00
|
|
|
my $bNoStartStop = false; # Do not perform start/stop backup (and archive-required gets set to false)
|
|
|
|
my $bForce = false; # Force an action that would not normally be allowed (varies by action)
|
|
|
|
my $bVersion = false; # Display version and exit
|
|
|
|
my $bHelp = false; # Display help and exit
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-13 17:37:16 +03:00
|
|
|
# Test parameters - not for general use
|
|
|
|
my $bNoFork = false; # Prevents the archive process from forking when local archiving is enabled
|
2014-07-27 21:03:21 +03:00
|
|
|
my $bTest = false; # Enters test mode - not harmful in anyway, but adds special logging and pauses for unit testing
|
2014-08-10 01:35:55 +03:00
|
|
|
my $iTestDelay = 5; # Amount of time to delay after hitting a test point (the default would not be enough for manual tests)
|
2014-07-13 17:37:16 +03:00
|
|
|
|
2014-09-20 00:51:51 +03:00
|
|
|
GetOptions ('config=s' => \$strConfigFile,
|
|
|
|
'stanza=s' => \$strStanza,
|
|
|
|
'type=s' => \$strType,
|
|
|
|
'no-start-stop' => \$bNoStartStop,
|
|
|
|
'force' => \$bForce,
|
|
|
|
'version' => \$bVersion,
|
|
|
|
'help' => \$bHelp,
|
2014-07-13 17:37:16 +03:00
|
|
|
|
2014-08-13 03:00:52 +03:00
|
|
|
# Test parameters - not for general use (and subject to change without notice)
|
2014-09-20 00:51:51 +03:00
|
|
|
'no-fork' => \$bNoFork,
|
|
|
|
'test' => \$bTest,
|
|
|
|
'test-delay=s' => \$iTestDelay)
|
2014-08-15 17:48:50 +03:00
|
|
|
or pod2usage(2);
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-08-15 17:48:50 +03:00
|
|
|
# Display version and exit if requested
|
|
|
|
if ($bVersion || $bHelp)
|
2014-08-13 03:00:52 +03:00
|
|
|
{
|
|
|
|
print 'pg_backrest ' . version_get() . "\n";
|
2014-08-15 17:48:50 +03:00
|
|
|
|
|
|
|
if (!$bHelp)
|
|
|
|
{
|
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Display help and exit if requested
|
|
|
|
if ($bHelp)
|
|
|
|
{
|
|
|
|
print "\n";
|
|
|
|
pod2usage();
|
2014-08-13 03:00:52 +03:00
|
|
|
}
|
|
|
|
|
2014-07-28 01:13:23 +03:00
|
|
|
# Set test parameters
|
|
|
|
test_set($bTest, $iTestDelay);
|
2014-07-27 21:03:21 +03:00
|
|
|
|
2014-12-16 00:20:42 +02:00
|
|
|
# Load the config file
|
|
|
|
config_load($strConfigFile, $strStanza);
|
|
|
|
|
2014-03-30 01:16:08 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# Global variables
|
|
|
|
####################################################################################################################################
|
2014-06-30 00:23:34 +03:00
|
|
|
my $oRemote; # Remote object
|
2014-07-13 02:03:39 +03:00
|
|
|
my $strRemote; # Defines which side is remote, DB or BACKUP
|
2014-06-04 18:58:30 +03:00
|
|
|
|
2014-06-30 00:23:34 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# REMOTE_EXIT - Close the remote object if it exists
|
|
|
|
####################################################################################################################################
|
|
|
|
sub remote_exit
|
|
|
|
{
|
|
|
|
my $iExitCode = shift;
|
|
|
|
|
|
|
|
if (defined($oRemote))
|
|
|
|
{
|
|
|
|
$oRemote->thread_kill()
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defined($iExitCode))
|
|
|
|
{
|
|
|
|
exit $iExitCode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# REMOTE_GET - Get the remote object or create it if not exists
|
|
|
|
####################################################################################################################################
|
2014-10-14 15:27:50 +03:00
|
|
|
sub remote_get
|
2014-07-13 02:03:39 +03:00
|
|
|
{
|
|
|
|
if (!defined($oRemote) && $strRemote ne REMOTE_NONE)
|
|
|
|
{
|
2014-10-08 20:54:31 +03:00
|
|
|
$oRemote = new BackRest::Remote
|
2014-07-13 02:03:39 +03:00
|
|
|
(
|
2014-10-08 20:54:31 +03:00
|
|
|
config_key_load($strRemote eq REMOTE_DB ? CONFIG_SECTION_STANZA : CONFIG_SECTION_BACKUP, CONFIG_KEY_HOST, true),
|
|
|
|
config_key_load($strRemote eq REMOTE_DB ? CONFIG_SECTION_STANZA : CONFIG_SECTION_BACKUP, CONFIG_KEY_USER, true),
|
|
|
|
config_key_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_REMOTE, true)
|
2014-07-13 02:03:39 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $oRemote;
|
|
|
|
}
|
|
|
|
|
2014-03-06 03:53:13 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# SAFE_EXIT - terminate all SSH sessions when the script is terminated
|
|
|
|
####################################################################################################################################
|
|
|
|
sub safe_exit
|
|
|
|
{
|
2014-06-30 00:23:34 +03:00
|
|
|
remote_exit();
|
|
|
|
|
2014-03-06 03:53:13 +03:00
|
|
|
my $iTotal = backup_thread_kill();
|
|
|
|
|
|
|
|
confess &log(ERROR, "process was terminated on signal, ${iTotal} threads stopped");
|
|
|
|
}
|
|
|
|
|
|
|
|
$SIG{TERM} = \&safe_exit;
|
|
|
|
$SIG{HUP} = \&safe_exit;
|
|
|
|
$SIG{INT} = \&safe_exit;
|
|
|
|
|
2014-07-28 01:13:23 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# START EVAL BLOCK TO CATCH ERRORS AND STOP THREADS
|
|
|
|
####################################################################################################################################
|
|
|
|
eval {
|
|
|
|
|
2014-03-06 03:53:13 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# START MAIN
|
|
|
|
####################################################################################################################################
|
|
|
|
# Get the operation
|
|
|
|
my $strOperation = $ARGV[0];
|
|
|
|
|
|
|
|
# Validate the operation
|
|
|
|
if (!defined($strOperation))
|
|
|
|
{
|
2014-09-16 15:55:40 +03:00
|
|
|
confess &log(ERROR, 'operation is not defined');
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
|
2014-03-30 01:16:08 +03:00
|
|
|
if ($strOperation ne OP_ARCHIVE_GET &&
|
|
|
|
$strOperation ne OP_ARCHIVE_PUSH &&
|
2014-03-06 03:53:13 +03:00
|
|
|
$strOperation ne OP_BACKUP &&
|
|
|
|
$strOperation ne OP_EXPIRE)
|
|
|
|
{
|
|
|
|
confess &log(ERROR, "invalid operation ${strOperation}");
|
|
|
|
}
|
|
|
|
|
|
|
|
# Type should only be specified for backups
|
|
|
|
if (defined($strType) && $strOperation ne OP_BACKUP)
|
|
|
|
{
|
2014-09-16 15:55:40 +03:00
|
|
|
confess &log(ERROR, 'type can only be specified for the backup operation')
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
|
2014-06-22 17:30:17 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
# DETERMINE IF THERE IS A REMOTE
|
|
|
|
####################################################################################################################################
|
|
|
|
# First check if backup is remote
|
2014-07-27 21:26:07 +03:00
|
|
|
if (defined(config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_HOST)))
|
2014-06-22 17:30:17 +03:00
|
|
|
{
|
|
|
|
$strRemote = REMOTE_BACKUP;
|
|
|
|
}
|
|
|
|
# Else check if db is remote
|
2014-07-27 21:26:07 +03:00
|
|
|
elsif (defined(config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_HOST)))
|
2014-06-22 17:30:17 +03:00
|
|
|
{
|
|
|
|
# Don't allow both sides to be remote
|
|
|
|
if (defined($strRemote))
|
|
|
|
{
|
|
|
|
confess &log(ERROR, 'db and backup cannot both be configured as remote');
|
|
|
|
}
|
2014-06-22 17:54:31 +03:00
|
|
|
|
2014-06-22 17:30:17 +03:00
|
|
|
$strRemote = REMOTE_DB;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$strRemote = REMOTE_NONE;
|
|
|
|
}
|
|
|
|
|
2014-03-06 03:53:13 +03:00
|
|
|
####################################################################################################################################
|
2014-07-13 02:03:39 +03:00
|
|
|
# ARCHIVE-PUSH Command
|
2014-03-30 01:16:08 +03:00
|
|
|
####################################################################################################################################
|
2014-07-13 02:03:39 +03:00
|
|
|
if ($strOperation eq OP_ARCHIVE_PUSH)
|
2014-03-30 01:16:08 +03:00
|
|
|
{
|
2014-07-13 02:03:39 +03:00
|
|
|
# Make sure the archive push operation happens on the db side
|
|
|
|
if ($strRemote eq REMOTE_DB)
|
2014-03-30 01:16:08 +03:00
|
|
|
{
|
2014-07-13 02:03:39 +03:00
|
|
|
confess &log(ERROR, 'archive-push operation must run on the db host');
|
2014-03-30 01:16:08 +03:00
|
|
|
}
|
|
|
|
|
2014-03-06 03:53:13 +03:00
|
|
|
# If an archive section has been defined, use that instead of the backup section when operation is OP_ARCHIVE_PUSH
|
2014-07-27 21:26:07 +03:00
|
|
|
my $bArchiveLocal = defined(config_key_load(CONFIG_SECTION_ARCHIVE, CONFIG_KEY_PATH));
|
2014-07-13 02:03:39 +03:00
|
|
|
my $strSection = $bArchiveLocal ? CONFIG_SECTION_ARCHIVE : CONFIG_SECTION_BACKUP;
|
2014-07-27 21:26:07 +03:00
|
|
|
my $strArchivePath = config_key_load($strSection, CONFIG_KEY_PATH);
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-16 05:32:41 +03:00
|
|
|
# Get checksum flag
|
2014-09-14 22:55:27 +03:00
|
|
|
my $bChecksum = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_CHECKSUM, true, 'y') eq 'y' ? true : false;
|
2014-07-16 05:32:41 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Get the async compress flag. If compress_async=y then compression is off for the initial push when archiving locally
|
|
|
|
my $bCompressAsync = false;
|
2014-06-04 18:58:30 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
if ($bArchiveLocal)
|
|
|
|
{
|
2014-09-14 22:55:27 +03:00
|
|
|
config_key_load($strSection, CONFIG_KEY_COMPRESS_ASYNC, true, 'n') eq 'n' ? false : true;
|
2014-07-13 02:03:39 +03:00
|
|
|
}
|
2014-03-06 03:53:13 +03:00
|
|
|
|
|
|
|
# If logging locally then create the stop archiving file name
|
2014-07-13 02:03:39 +03:00
|
|
|
my $strStopFile;
|
|
|
|
|
|
|
|
if ($bArchiveLocal)
|
2014-03-06 03:53:13 +03:00
|
|
|
{
|
|
|
|
$strStopFile = "${strArchivePath}/lock/${strStanza}-archive.stop";
|
|
|
|
}
|
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# If an archive file is defined, then push it
|
|
|
|
if (defined($ARGV[1]))
|
2014-03-06 03:53:13 +03:00
|
|
|
{
|
|
|
|
# If the stop file exists then discard the archive log
|
|
|
|
if (defined($strStopFile))
|
|
|
|
{
|
|
|
|
if (-e $strStopFile)
|
|
|
|
{
|
2014-07-13 02:03:39 +03:00
|
|
|
&log(ERROR, "archive stop file (${strStopFile}) exists , discarding " . basename($ARGV[1]));
|
2014-06-30 00:23:34 +03:00
|
|
|
remote_exit(0);
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
}
|
2014-06-04 18:58:30 +03:00
|
|
|
|
2014-03-06 03:53:13 +03:00
|
|
|
# Get the compress flag
|
2014-09-14 22:55:27 +03:00
|
|
|
my $bCompress = $bCompressAsync ? false : config_key_load($strSection, CONFIG_KEY_COMPRESS, true, 'y') eq 'y' ? true : false;
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Create the file object
|
2014-10-10 22:13:28 +03:00
|
|
|
my $oFile = new BackRest::File
|
2014-03-06 03:53:13 +03:00
|
|
|
(
|
2014-10-10 22:13:28 +03:00
|
|
|
$strStanza,
|
|
|
|
config_key_load($strSection, CONFIG_KEY_PATH, true),
|
|
|
|
$bArchiveLocal ? REMOTE_NONE : $strRemote,
|
|
|
|
$bArchiveLocal ? undef : remote_get()
|
2014-03-06 03:53:13 +03:00
|
|
|
);
|
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Init backup
|
2014-03-06 03:53:13 +03:00
|
|
|
backup_init
|
|
|
|
(
|
|
|
|
undef,
|
|
|
|
$oFile,
|
|
|
|
undef,
|
2014-06-24 02:08:36 +03:00
|
|
|
$bCompress,
|
2014-03-06 03:53:13 +03:00
|
|
|
undef,
|
|
|
|
!$bChecksum
|
|
|
|
);
|
|
|
|
|
2014-09-14 22:55:27 +03:00
|
|
|
&log(INFO, 'pushing archive log ' . $ARGV[1] . ($bArchiveLocal ? ' asynchronously' : ''));
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-27 21:26:07 +03:00
|
|
|
archive_push(config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH), $ARGV[1]);
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Exit if we are archiving local but no backup host has been defined
|
2014-07-27 21:26:07 +03:00
|
|
|
if (!($bArchiveLocal && defined(config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_HOST))))
|
2014-03-06 03:53:13 +03:00
|
|
|
{
|
2014-06-30 00:23:34 +03:00
|
|
|
remote_exit(0);
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Fork and exit the parent process so the async process can continue
|
2014-07-13 17:37:16 +03:00
|
|
|
if (!$bNoFork)
|
2014-03-06 03:53:13 +03:00
|
|
|
{
|
2014-07-13 17:37:16 +03:00
|
|
|
if (fork())
|
|
|
|
{
|
|
|
|
remote_exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# Else the no-fork flag has been specified for testing
|
|
|
|
else
|
|
|
|
{
|
2014-09-14 22:55:27 +03:00
|
|
|
&log(INFO, 'No fork on archive local for TESTING');
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# If no backup host is defined it makes no sense to run archive-push without a specified archive file so throw an error
|
2014-07-27 21:26:07 +03:00
|
|
|
if (!defined(config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_HOST)))
|
2014-03-06 03:53:13 +03:00
|
|
|
{
|
2014-09-14 22:55:27 +03:00
|
|
|
&log(ERROR, 'archive-push called without an archive file or backup host');
|
2014-07-13 02:03:39 +03:00
|
|
|
}
|
2014-06-04 18:58:30 +03:00
|
|
|
|
2014-09-14 22:55:27 +03:00
|
|
|
&log(INFO, 'starting async archive-push');
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Create a lock file to make sure async archive-push does not run more than once
|
|
|
|
my $strLockPath = "${strArchivePath}/lock/${strStanza}-archive.lock";
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
if (!lock_file_create($strLockPath))
|
|
|
|
{
|
2014-09-14 22:55:27 +03:00
|
|
|
&log(DEBUG, 'archive-push process is already running - exiting');
|
2014-07-13 02:03:39 +03:00
|
|
|
remote_exit(0);
|
|
|
|
}
|
2014-07-13 17:37:16 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Build the basic command string that will be used to modify the command during processing
|
2014-09-16 15:55:40 +03:00
|
|
|
my $strCommand = $^X . ' ' . $0 . " --stanza=${strStanza}";
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Get the new operational flags
|
2014-09-14 22:55:27 +03:00
|
|
|
my $bCompress = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_COMPRESS, true, 'y') eq 'y' ? true : false;
|
2014-07-27 21:26:07 +03:00
|
|
|
my $iArchiveMaxMB = config_key_load(CONFIG_SECTION_ARCHIVE, CONFIG_KEY_ARCHIVE_MAX_MB);
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# eval
|
|
|
|
# {
|
|
|
|
# Create the file object
|
2014-10-10 22:13:28 +03:00
|
|
|
my $oFile = new BackRest::File
|
2014-07-13 02:03:39 +03:00
|
|
|
(
|
2014-10-10 22:13:28 +03:00
|
|
|
$strStanza,
|
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
|
|
|
$strRemote,
|
|
|
|
remote_get()
|
2014-07-13 02:03:39 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
# Init backup
|
|
|
|
backup_init
|
|
|
|
(
|
|
|
|
undef,
|
|
|
|
$oFile,
|
|
|
|
undef,
|
|
|
|
$bCompress,
|
|
|
|
undef,
|
|
|
|
!$bChecksum,
|
2014-07-27 21:26:07 +03:00
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_MAX),
|
2014-07-13 02:03:39 +03:00
|
|
|
undef,
|
2014-07-27 21:26:07 +03:00
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_TIMEOUT)
|
2014-07-13 02:03:39 +03:00
|
|
|
);
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-13 17:37:16 +03:00
|
|
|
# Call the archive_xfer function and continue to loop as long as there are files to process
|
2014-07-13 02:03:39 +03:00
|
|
|
my $iLogTotal;
|
|
|
|
|
|
|
|
while (!defined($iLogTotal) || $iLogTotal > 0)
|
2014-03-06 03:53:13 +03:00
|
|
|
{
|
2014-07-13 17:37:16 +03:00
|
|
|
$iLogTotal = archive_xfer($strArchivePath . "/archive/${strStanza}", $strStopFile, $strCommand, $iArchiveMaxMB);
|
2014-07-13 02:03:39 +03:00
|
|
|
|
|
|
|
if ($iLogTotal > 0)
|
2014-03-06 03:53:13 +03:00
|
|
|
{
|
2014-07-13 17:37:16 +03:00
|
|
|
&log(DEBUG, "${iLogTotal} archive logs were transferred, calling archive_xfer() again");
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-09-14 22:55:27 +03:00
|
|
|
&log(DEBUG, 'no more logs to transfer - exiting');
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
}
|
2014-07-13 02:03:39 +03:00
|
|
|
#
|
|
|
|
# };
|
|
|
|
|
|
|
|
# # If there were errors above then start compressing
|
|
|
|
# if ($@)
|
|
|
|
# {
|
|
|
|
# if ($bCompressAsync)
|
|
|
|
# {
|
|
|
|
# &log(ERROR, "error during transfer: $@");
|
|
|
|
# &log(WARN, "errors during transfer, starting compression");
|
|
|
|
#
|
|
|
|
# # Run file_init_archive - this is the minimal config needed to run archive pulling !!! need to close the old file
|
|
|
|
# my $oFile = BackRest::File->new
|
|
|
|
# (
|
|
|
|
# # strStanza => $strStanza,
|
|
|
|
# # bNoCompression => false,
|
2014-07-27 21:26:07 +03:00
|
|
|
# # strBackupPath => config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
2014-07-13 02:03:39 +03:00
|
|
|
# # strCommand => $0,
|
2014-07-27 21:26:07 +03:00
|
|
|
# # strCommandCompress => config_key_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_COMPRESS, $bCompress),
|
|
|
|
# # strCommandDecompress => config_key_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_DECOMPRESS, $bCompress)
|
2014-07-13 02:03:39 +03:00
|
|
|
# );
|
|
|
|
#
|
|
|
|
# backup_init
|
|
|
|
# (
|
|
|
|
# undef,
|
|
|
|
# $oFile,
|
|
|
|
# undef,
|
|
|
|
# $bCompress,
|
|
|
|
# undef,
|
|
|
|
# !$bChecksum,
|
2014-07-27 21:26:07 +03:00
|
|
|
# config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_MAX),
|
2014-07-13 02:03:39 +03:00
|
|
|
# undef,
|
2014-07-27 21:26:07 +03:00
|
|
|
# config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_TIMEOUT)
|
2014-07-13 02:03:39 +03:00
|
|
|
# );
|
|
|
|
#
|
|
|
|
# archive_compress($strArchivePath . "/archive/${strStanza}", $strCommand, 256);
|
|
|
|
# }
|
|
|
|
# else
|
|
|
|
# {
|
|
|
|
# confess $@;
|
|
|
|
# }
|
|
|
|
# }
|
|
|
|
|
|
|
|
lock_file_remove();
|
|
|
|
remote_exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# ARCHIVE-GET Command
|
|
|
|
####################################################################################################################################
|
|
|
|
if ($strOperation eq OP_ARCHIVE_GET)
|
|
|
|
{
|
|
|
|
# Make sure the archive file is defined
|
|
|
|
if (!defined($ARGV[1]))
|
|
|
|
{
|
2014-09-14 22:55:27 +03:00
|
|
|
confess &log(ERROR, 'archive file not provided');
|
2014-07-13 02:03:39 +03:00
|
|
|
}
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Make sure the destination file is defined
|
|
|
|
if (!defined($ARGV[2]))
|
|
|
|
{
|
2014-09-14 22:55:27 +03:00
|
|
|
confess &log(ERROR, 'destination file not provided');
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
|
2014-07-13 02:03:39 +03:00
|
|
|
# Init the file object
|
2014-10-10 22:13:28 +03:00
|
|
|
my $oFile = new BackRest::File
|
2014-07-13 02:03:39 +03:00
|
|
|
(
|
2014-10-10 22:13:28 +03:00
|
|
|
$strStanza,
|
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
|
|
|
$strRemote,
|
|
|
|
remote_get()
|
2014-07-13 02:03:39 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
# Init the backup object
|
|
|
|
backup_init
|
|
|
|
(
|
|
|
|
undef,
|
|
|
|
$oFile
|
|
|
|
);
|
|
|
|
|
|
|
|
# Info for the Postgres log
|
2014-09-14 22:55:27 +03:00
|
|
|
&log(INFO, 'getting archive log ' . $ARGV[1]);
|
2014-07-13 02:03:39 +03:00
|
|
|
|
|
|
|
# Get the archive file
|
2014-09-30 01:51:02 +03:00
|
|
|
remote_exit(archive_get(config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH), $ARGV[1], $ARGV[2]));
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# OPEN THE LOG FILE
|
|
|
|
####################################################################################################################################
|
2014-07-27 21:26:07 +03:00
|
|
|
if (defined(config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_HOST)))
|
2014-03-06 03:53:13 +03:00
|
|
|
{
|
2014-09-14 22:55:27 +03:00
|
|
|
confess &log(ASSERT, 'backup/expire operations must be performed locally on the backup server');
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
|
2014-07-27 21:26:07 +03:00
|
|
|
log_file_set(config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true) . "/log/${strStanza}");
|
2014-03-06 03:53:13 +03:00
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# GET MORE CONFIG INFO
|
|
|
|
####################################################################################################################################
|
2014-07-13 02:03:39 +03:00
|
|
|
# Make sure backup and expire operations happen on the backup side
|
2014-06-22 21:51:28 +03:00
|
|
|
if ($strRemote eq REMOTE_BACKUP)
|
2014-06-22 17:30:17 +03:00
|
|
|
{
|
|
|
|
confess &log(ERROR, 'backup and expire operations must run on the backup host');
|
|
|
|
}
|
|
|
|
|
2014-03-06 03:53:13 +03:00
|
|
|
# Set the backup type
|
|
|
|
if (!defined($strType))
|
|
|
|
{
|
2014-10-14 15:27:50 +03:00
|
|
|
$strType = BACKUP_TYPE_INCR;
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
2014-10-14 15:27:50 +03:00
|
|
|
elsif ($strType ne BACKUP_TYPE_FULL && $strType ne BACKUP_TYPE_DIFF && $strType ne BACKUP_TYPE_INCR)
|
2014-03-06 03:53:13 +03:00
|
|
|
{
|
2014-10-14 15:27:50 +03:00
|
|
|
confess &log(ERROR, 'backup type must be full, diff (differential), incr (incremental)');
|
2014-03-06 03:53:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
# Get the operational flags
|
2014-09-14 22:55:27 +03:00
|
|
|
my $bCompress = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_COMPRESS, true, 'y') eq 'y' ? true : false;
|
|
|
|
my $bChecksum = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_CHECKSUM, true, 'y') eq 'y' ? true : false;
|
2014-03-06 03:53:13 +03:00
|
|
|
|
2014-04-28 16:13:25 +03:00
|
|
|
# Set the lock path
|
2014-07-27 21:26:07 +03:00
|
|
|
my $strLockPath = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true) . "/lock/${strStanza}-${strOperation}.lock";
|
2014-04-28 16:13:25 +03:00
|
|
|
|
|
|
|
if (!lock_file_create($strLockPath))
|
|
|
|
{
|
|
|
|
&log(ERROR, "backup process is already running for stanza ${strStanza} - exiting");
|
2014-06-30 00:23:34 +03:00
|
|
|
remote_exit(0);
|
2014-04-28 16:13:25 +03:00
|
|
|
}
|
|
|
|
|
2014-09-20 00:51:51 +03:00
|
|
|
# Initialize the default file object
|
2014-10-10 22:13:28 +03:00
|
|
|
my $oFile = new BackRest::File
|
2014-03-06 03:53:13 +03:00
|
|
|
(
|
2014-10-10 22:13:28 +03:00
|
|
|
$strStanza,
|
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
|
|
|
$strRemote,
|
|
|
|
remote_get()
|
2014-03-06 03:53:13 +03:00
|
|
|
);
|
|
|
|
|
2014-09-20 00:51:51 +03:00
|
|
|
# Initialize the db object
|
|
|
|
my $oDb;
|
|
|
|
|
|
|
|
if (!$bNoStartStop)
|
|
|
|
{
|
2014-10-10 23:03:33 +03:00
|
|
|
$oDb = new BackRest::Db
|
2014-09-20 00:51:51 +03:00
|
|
|
(
|
2014-10-10 23:03:33 +03:00
|
|
|
config_key_load(CONFIG_SECTION_COMMAND, CONFIG_KEY_PSQL),
|
|
|
|
config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_HOST),
|
|
|
|
config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_USER)
|
2014-09-20 00:51:51 +03:00
|
|
|
);
|
|
|
|
}
|
2014-03-06 03:53:13 +03:00
|
|
|
|
|
|
|
# Run backup_init - parameters required for backup and restore operations
|
|
|
|
backup_init
|
|
|
|
(
|
|
|
|
$oDb,
|
|
|
|
$oFile,
|
|
|
|
$strType,
|
2014-09-14 22:55:27 +03:00
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_COMPRESS, true, 'y') eq 'y' ? true : false,
|
2014-09-16 01:12:30 +03:00
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_HARDLINK, true, 'y') eq 'y' ? true : false,
|
2014-03-06 03:53:13 +03:00
|
|
|
!$bChecksum,
|
2014-07-27 21:26:07 +03:00
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_MAX),
|
2014-09-14 22:55:27 +03:00
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_ARCHIVE_REQUIRED, true, 'y') eq 'y' ? true : false,
|
2014-07-27 21:26:07 +03:00
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_TIMEOUT),
|
2014-09-20 00:51:51 +03:00
|
|
|
$bNoStartStop,
|
|
|
|
$bForce
|
2014-03-06 03:53:13 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# BACKUP
|
|
|
|
####################################################################################################################################
|
|
|
|
if ($strOperation eq OP_BACKUP)
|
|
|
|
{
|
2014-07-27 21:26:07 +03:00
|
|
|
backup(config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH),
|
2014-09-14 22:55:27 +03:00
|
|
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_START_FAST, true, 'n') eq 'y' ? true : false);
|
2014-03-06 03:53:13 +03:00
|
|
|
|
|
|
|
$strOperation = OP_EXPIRE;
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# EXPIRE
|
|
|
|
####################################################################################################################################
|
|
|
|
if ($strOperation eq OP_EXPIRE)
|
|
|
|
{
|
|
|
|
backup_expire
|
|
|
|
(
|
|
|
|
$oFile->path_get(PATH_BACKUP_CLUSTER),
|
2014-09-14 22:55:27 +03:00
|
|
|
config_key_load(CONFIG_SECTION_RETENTION, CONFIG_KEY_FULL_RETENTION),
|
|
|
|
config_key_load(CONFIG_SECTION_RETENTION, CONFIG_KEY_DIFFERENTIAL_RETENTION),
|
|
|
|
config_key_load(CONFIG_SECTION_RETENTION, CONFIG_KEY_ARCHIVE_RETENTION_TYPE),
|
|
|
|
config_key_load(CONFIG_SECTION_RETENTION, CONFIG_KEY_ARCHIVE_RETENTION)
|
2014-03-06 03:53:13 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
lock_file_remove();
|
|
|
|
}
|
|
|
|
|
2014-06-30 00:23:34 +03:00
|
|
|
remote_exit(0);
|
2014-08-10 22:02:14 +03:00
|
|
|
};
|
2014-07-28 01:13:23 +03:00
|
|
|
|
|
|
|
####################################################################################################################################
|
2014-08-10 22:02:14 +03:00
|
|
|
# CHECK FOR ERRORS AND STOP THREADS
|
2014-07-28 01:13:23 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
if ($@)
|
|
|
|
{
|
|
|
|
remote_exit();
|
|
|
|
confess $@;
|
|
|
|
}
|