You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-05-22 10:15:16 +02:00
f54145c0cc
* Fixed an issue where local processes were not disconnecting when complete and could later timeout. (Reported by Todd Vernick.) * Fixed an issue where the protocol layer could timeout while waiting for WAL segments to arrive in the archive. (Reported by Todd Vernick.)
256 lines
10 KiB
Perl
Executable File
256 lines
10 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
####################################################################################################################################
|
|
# pgBackRest - Simple PostgreSQL Backup and Restore
|
|
####################################################################################################################################
|
|
|
|
####################################################################################################################################
|
|
# Perl includes
|
|
####################################################################################################################################
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
use English '-no_match_vars';
|
|
|
|
# Convert die to confess to capture the stack trace
|
|
$SIG{__DIE__} = sub { Carp::confess @_ };
|
|
|
|
use File::Basename qw(dirname);
|
|
|
|
use lib dirname($0) . '/../lib';
|
|
use pgBackRest::Archive;
|
|
use pgBackRest::Common::Exception;
|
|
use pgBackRest::Common::Exit;
|
|
use pgBackRest::Common::Lock;
|
|
use pgBackRest::Common::Log;
|
|
use pgBackRest::Config::Config;
|
|
use pgBackRest::File;
|
|
use pgBackRest::Protocol::Common;
|
|
use pgBackRest::Protocol::Protocol;
|
|
|
|
####################################################################################################################################
|
|
# Run in eval block to catch errors
|
|
####################################################################################################################################
|
|
local $EVAL_ERROR = undef; eval
|
|
{
|
|
################################################################################################################################
|
|
# Load command line parameters and config
|
|
################################################################################################################################
|
|
my $bConfigResult = configLoad();
|
|
|
|
# Display help and version
|
|
if (commandTest(CMD_HELP) || commandTest(CMD_VERSION))
|
|
{
|
|
# Load module dynamically
|
|
require pgBackRest::Config::ConfigHelp;
|
|
pgBackRest::Config::ConfigHelp->import();
|
|
|
|
# Generate help and exit
|
|
configHelp($ARGV[1], $ARGV[2], commandTest(CMD_VERSION), $bConfigResult);
|
|
exitSafe(0);
|
|
}
|
|
|
|
# Set test options
|
|
if (optionTest(OPTION_TEST) && optionGet(OPTION_TEST))
|
|
{
|
|
testSet(optionGet(OPTION_TEST), optionGet(OPTION_TEST_DELAY), optionGet(OPTION_TEST_POINT, false));
|
|
}
|
|
|
|
################################################################################################################################
|
|
# Process remote commands
|
|
################################################################################################################################
|
|
if (commandTest(CMD_REMOTE))
|
|
{
|
|
# Set log levels
|
|
logLevelSet(OFF, REMOTE);
|
|
|
|
# Check that the repo path exists if this is a backup remote
|
|
if (optionTest(OPTION_TYPE, BACKUP) && !-e optionGet(OPTION_REPO_PATH))
|
|
{
|
|
confess &log(ERROR, 'repo-path \'' . optionGet(OPTION_REPO_PATH) . '\' does not exist', ERROR_PATH_MISSING);
|
|
}
|
|
|
|
# Load module dynamically
|
|
require pgBackRest::Protocol::RemoteMinion;
|
|
pgBackRest::Protocol::RemoteMinion->import();
|
|
|
|
# Create the remote object
|
|
my $oRemote = new pgBackRest::Protocol::RemoteMinion
|
|
(
|
|
optionGet(OPTION_COMMAND),
|
|
optionGet(OPTION_BUFFER_SIZE),
|
|
optionGet(OPTION_COMPRESS_LEVEL),
|
|
optionGet(OPTION_COMPRESS_LEVEL_NETWORK),
|
|
optionGet(OPTION_PROTOCOL_TIMEOUT)
|
|
);
|
|
|
|
# Acquire a remote lock
|
|
lockAcquire(optionGet(OPTION_COMMAND), undef, true, optionGet(OPTION_PROCESS, false));
|
|
|
|
# Process remote requests
|
|
exitSafe($oRemote->process());
|
|
}
|
|
|
|
################################################################################################################################
|
|
# Process local commands
|
|
################################################################################################################################
|
|
if (commandTest(CMD_LOCAL))
|
|
{
|
|
# Set log levels
|
|
logLevelSet(OFF, REMOTE);
|
|
|
|
# Load module dynamically
|
|
require pgBackRest::Protocol::LocalMinion;
|
|
pgBackRest::Protocol::LocalMinion->import();
|
|
|
|
# Create the local object
|
|
my $oLocal = new pgBackRest::Protocol::LocalMinion(optionGet(OPTION_COMMAND));
|
|
|
|
# Acquire a local lock
|
|
lockAcquire(optionGet(OPTION_COMMAND), undef, true, optionGet(OPTION_PROCESS, false));
|
|
|
|
# Process local requests
|
|
exitSafe($oLocal->process());
|
|
}
|
|
|
|
# Log the command start
|
|
commandStart();
|
|
|
|
# Check that the repo path exists
|
|
if (isRepoLocal() && !-e optionGet(OPTION_REPO_PATH))
|
|
{
|
|
confess &log(ERROR, 'repo-path \'' . optionGet(OPTION_REPO_PATH) . '\' does not exist', ERROR_PATH_MISSING);
|
|
}
|
|
|
|
################################################################################################################################
|
|
# Process archive commands
|
|
################################################################################################################################
|
|
if (commandTest(CMD_ARCHIVE_PUSH) || commandTest(CMD_ARCHIVE_GET))
|
|
{
|
|
if (!isDbLocal())
|
|
{
|
|
confess &log(ERROR, commandGet() . ' command must be run on the db host', ERROR_HOST_INVALID);
|
|
}
|
|
|
|
exitSafe(new pgBackRest::Archive()->process());
|
|
}
|
|
|
|
################################################################################################################################
|
|
# Process check command
|
|
################################################################################################################################
|
|
if (commandTest(CMD_CHECK))
|
|
{
|
|
exitSafe(new pgBackRest::Archive()->check());
|
|
}
|
|
|
|
################################################################################################################################
|
|
# Process start/stop commands
|
|
################################################################################################################################
|
|
if (commandTest(CMD_START))
|
|
{
|
|
lockStart();
|
|
exitSafe(0);
|
|
}
|
|
elsif (commandTest(CMD_STOP))
|
|
{
|
|
lockStop();
|
|
exitSafe(0);
|
|
}
|
|
|
|
################################################################################################################################
|
|
# Process info command
|
|
################################################################################################################################
|
|
if (commandTest(CMD_INFO))
|
|
{
|
|
# Load module dynamically
|
|
require pgBackRest::Info;
|
|
pgBackRest::Info->import();
|
|
|
|
exitSafe(new pgBackRest::Info()->process());
|
|
}
|
|
|
|
################################################################################################################################
|
|
# Acquire the command lock
|
|
################################################################################################################################
|
|
lockAcquire(commandGet());
|
|
|
|
################################################################################################################################
|
|
# Open the log file
|
|
################################################################################################################################
|
|
logFileSet(optionGet(OPTION_LOG_PATH) . '/' . optionGet(OPTION_STANZA) . '-' . lc(commandGet()));
|
|
|
|
################################################################################################################################
|
|
# RESTORE
|
|
################################################################################################################################
|
|
if (commandTest(CMD_RESTORE))
|
|
{
|
|
if (!isDbLocal())
|
|
{
|
|
confess &log(ERROR, 'restore command must be run on the db host', ERROR_HOST_INVALID);
|
|
}
|
|
|
|
# Load module dynamically
|
|
require pgBackRest::Restore;
|
|
pgBackRest::Restore->import();
|
|
|
|
# Do the restore
|
|
new pgBackRest::Restore()->process();
|
|
|
|
exitSafe(0);
|
|
}
|
|
else
|
|
{
|
|
############################################################################################################################
|
|
# Make sure backup and expire commands happen on the backup side
|
|
############################################################################################################################
|
|
if (!isRepoLocal())
|
|
{
|
|
confess &log(ERROR, 'backup and expire commands must be run on the backup host', ERROR_HOST_INVALID);
|
|
}
|
|
|
|
############################################################################################################################
|
|
# BACKUP
|
|
############################################################################################################################
|
|
if (commandTest(CMD_BACKUP))
|
|
{
|
|
# Load module dynamically
|
|
require pgBackRest::Backup;
|
|
pgBackRest::Backup->import();
|
|
|
|
new pgBackRest::Backup()->process();
|
|
|
|
commandSet(CMD_EXPIRE);
|
|
}
|
|
|
|
############################################################################################################################
|
|
# EXPIRE
|
|
############################################################################################################################
|
|
if (commandTest(CMD_EXPIRE))
|
|
{
|
|
# Load module dynamically
|
|
require pgBackRest::Expire;
|
|
pgBackRest::Expire->import();
|
|
|
|
new pgBackRest::Expire()->process();
|
|
}
|
|
}
|
|
|
|
lockRelease();
|
|
exitSafe(0);
|
|
|
|
# It shouldn't be possible to get here
|
|
&log(ASSERT, 'execution reached invalid location in ' . __FILE__ . ', line ' . __LINE__);
|
|
exit ERROR_ASSERT;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# Check for errors
|
|
####################################################################################################################################
|
|
or do
|
|
{
|
|
exitSafe(undef, $EVAL_ERROR);
|
|
};
|
|
|
|
# It shouldn't be possible to get here
|
|
&log(ASSERT, 'execution reached invalid location in ' . __FILE__ . ', line ' . __LINE__);
|
|
exit ERROR_ASSERT;
|