mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Add rsync remote user name option. Expand docs to
include command line help examples.
This commit is contained in:
147
README.rst
147
README.rst
@@ -32,7 +32,7 @@ To install and use repmgr and repmgrd follow these steps:
|
||||
|
||||
3. Check your primary server is correctly configured
|
||||
|
||||
4. Write a suitable repmgr.conf for the node
|
||||
4. Write a suitable ``repmgr.conf`` for the node
|
||||
|
||||
5. Setup repmgrd to aid in failover transitions
|
||||
|
||||
@@ -132,9 +132,9 @@ You may need to include
|
||||
the full path of the binary instead, such as this RHEL example::
|
||||
|
||||
/usr/pgsql-9.0/bin/repmgr --version
|
||||
/usr/pgsql-9.0/bin/repmgr --version
|
||||
/usr/pgsql-9.0/bin/repmgrd --version
|
||||
|
||||
Below this base binary installation directory is referred to as PGDIR.
|
||||
Below this binary installation base directory is referred to as PGDIR.
|
||||
|
||||
Set up trusted copy between postgres accounts
|
||||
---------------------------------------------
|
||||
@@ -172,7 +172,39 @@ user's account::
|
||||
Now test that ssh in both directions works. You may have to accept some new
|
||||
known hosts in the process.
|
||||
|
||||
CONFIGURATION FILE
|
||||
Primary server configuration
|
||||
============================
|
||||
|
||||
PostgreSQL should have been previously built and installed on the system. Here
|
||||
is a sample of changes to the ``postgresql.conf`` file::
|
||||
|
||||
listen_addresses='*'
|
||||
wal_level = 'hot_standby'
|
||||
archive_mode = on
|
||||
archive_command = 'cd .' # we can also use exit 0, anything that
|
||||
# just does nothing
|
||||
max_wal_senders = 10
|
||||
wal_keep_segments = 5000 # 80 GB required on pg_xlog
|
||||
hot_standby = on
|
||||
|
||||
Also you need to add the machines that will participate in the cluster in
|
||||
``pg_hba.conf`` file. One possibility is to trust all connections from the
|
||||
replication users from all internal addresses, such as::
|
||||
|
||||
host all all 192.168.1.0/24 trust
|
||||
host replication all 192.168.1.0/24 trust
|
||||
|
||||
A more secure setup adds a repmgr user and database, just giving
|
||||
access to that user::
|
||||
|
||||
host repmgr repmgr 192.168.1.0/24 trust
|
||||
host replication all 192.168.1.0/24 trust
|
||||
|
||||
If you give a password to the user, you need to create a ``.pgpass`` file for
|
||||
them as well to allow automatic login. In this case you might use the
|
||||
``md5`` authentication method instead of ``trust`` for the repmgr user.
|
||||
|
||||
Configuration File
|
||||
==================
|
||||
|
||||
``repmgr.conf`` is looked for in the directory repmgrd or repmgr exists.
|
||||
@@ -186,11 +218,52 @@ It should have these three parameters:
|
||||
|
||||
3. conninfo: A string (single quoted) specifying how we can connect to this node's PostgreSQL service
|
||||
|
||||
Command line syntax
|
||||
===================
|
||||
|
||||
The current supported syntax for the program can be seen using::
|
||||
|
||||
repmgr --help
|
||||
|
||||
The output from this program looks like this::
|
||||
|
||||
repmgr: Replicator manager
|
||||
Usage:
|
||||
repmgr [OPTIONS] master {register}
|
||||
repmgr [OPTIONS] standby {register|clone|promote|follow}
|
||||
|
||||
General options:
|
||||
--help show this help, then exit
|
||||
--version output version information, then exit
|
||||
--verbose output verbose activity information
|
||||
|
||||
Connection options:
|
||||
-d, --dbname=DBNAME database to connect to
|
||||
-h, --host=HOSTNAME database server host or socket directory
|
||||
-p, --port=PORT database server port
|
||||
-U, --username=USERNAME database user name to connect as
|
||||
|
||||
Configuration options:
|
||||
-D, --data-dir=DIR local directory where the files will be copied to
|
||||
-f, --config_file=PATH path to the configuration file
|
||||
-R, --remote-user=USERNAME database server username for rsync
|
||||
|
||||
repmgr performs some tasks like clone a node, promote it or making follow another node and then exits.
|
||||
COMMANDS:
|
||||
master register - registers the master in a cluster
|
||||
standby register - registers a standby in a cluster
|
||||
standby clone [node] - allows creation of a new standby
|
||||
standby promote - allows manual promotion of a specific standby into a new master in the event of a failover
|
||||
standby follow - allows the standby to re-point itself to a new master
|
||||
|
||||
The ``--verbose`` option can be useful in troubleshooting issues with
|
||||
the program.
|
||||
|
||||
Commands
|
||||
========
|
||||
|
||||
None of this commands need the ``repmgr.conf`` file but they need to be able to
|
||||
connect to the remote and local database.
|
||||
Not all of these commands need the ``repmgr.conf`` file, but they need to be able to
|
||||
connect to the remote and local databases.
|
||||
|
||||
You can teach it which is the remote database by using the -h parameter or
|
||||
as a last parameter in standby clone and standby follow. If you need to specify
|
||||
@@ -212,7 +285,7 @@ its port if is different from the default one.
|
||||
|
||||
* Backup via rsync the data directory of the primary. And creates the recovery file
|
||||
we need to start a new hot standby server.
|
||||
It doesn't need the repmgr.conf so it can be executed anywhere in the new node.
|
||||
It doesn't need the ``repmgr.conf`` so it can be executed anywhere in the new node.
|
||||
So, you can step where you want your new data directory and execute::
|
||||
|
||||
./repmgr standby clone 10.68.1.161
|
||||
@@ -245,38 +318,6 @@ its port if is different from the default one.
|
||||
|
||||
./repmgr standby follow
|
||||
|
||||
Primary server configuration
|
||||
============================
|
||||
|
||||
PostgreSQL should have been previously built and installed on the system. Here
|
||||
is a sample of changes to the postgresql.conf file::
|
||||
|
||||
listen_addresses='*'
|
||||
wal_level = 'hot_standby'
|
||||
archive_mode = on
|
||||
archive_command = 'cd .' # we can also use exit 0, anything that
|
||||
# just does nothing
|
||||
max_wal_senders = 10
|
||||
wal_keep_segments = 5000 # 80 GB required on pg_xlog
|
||||
hot_standby = on
|
||||
|
||||
Also you need to add the machines that will participate in the cluster in
|
||||
``pg_hba.conf`` file. One possibility is to trust all connections from the
|
||||
replication users from all internal addresses, such as::
|
||||
|
||||
host all all 192.168.1.0/24 trust
|
||||
host replication all 192.168.1.0/24 trust
|
||||
|
||||
A more secure setup adds a repmgr user and database, just giving
|
||||
access to that user::
|
||||
|
||||
host repmgr repmgr 192.168.1.0/24 trust
|
||||
host replication all 192.168.1.0/24 trust
|
||||
|
||||
If you give a password to the user, you need to create a ``.pgpass`` file for
|
||||
them as well to allow automatic login. In this case you might use the
|
||||
``md5`` authentication method instead of ``trust`` for the repmgr user.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
@@ -302,14 +343,38 @@ and run::
|
||||
|
||||
repmgr -D /var/lib/postgresql/9.0 standby clone node2
|
||||
|
||||
NOTE: you need to have PGDIR/bin in your path, if you don't want that as a
|
||||
permanent setting you can do it this way::
|
||||
NOTE: you need to have PGDIR/bin in your path. If you don't want that as a
|
||||
permanent setting, you can do it this way::
|
||||
|
||||
PATH=$PGDIR/bin:$PATH repmgr standby promote
|
||||
|
||||
repmgr Daemon
|
||||
=============
|
||||
|
||||
Command line syntax
|
||||
-------------------
|
||||
|
||||
The current supported syntax for the program can be seen using::
|
||||
|
||||
repmgrd --help
|
||||
|
||||
The output from this program looks like this::
|
||||
|
||||
repmgrd: Replicator manager daemon
|
||||
Usage:
|
||||
repmgrd [OPTIONS]
|
||||
|
||||
Options:
|
||||
--help show this help, then exit
|
||||
--version output version information, then exit
|
||||
--verbose output verbose activity information
|
||||
-f, --config_file=PATH database to connect to
|
||||
|
||||
repmgrd monitors a cluster of servers.
|
||||
|
||||
The ``--verbose`` option can be useful in troubleshooting issues with
|
||||
the program.
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
|
||||
93
repmgr.c
93
repmgr.c
@@ -30,9 +30,11 @@
|
||||
#define STANDBY_PROMOTE 4
|
||||
#define STANDBY_FOLLOW 5
|
||||
|
||||
#define QUERY_STR_LEN 8192
|
||||
|
||||
static void help(const char *progname);
|
||||
static bool create_recovery_file(const char *data_dir);
|
||||
static int copy_remote_files(char *host, char *remote_path, char *local_path, bool is_directory);
|
||||
static int copy_remote_files(char *host, char *remote_user, char *remote_path, char *local_path, bool is_directory);
|
||||
static bool check_parameters_for_action(const int action);
|
||||
|
||||
static void do_master_register(void);
|
||||
@@ -51,6 +53,7 @@ char *host = NULL;
|
||||
char *username = NULL;
|
||||
char *dest_dir = NULL;
|
||||
char *config_file = NULL;
|
||||
char *remote_user = NULL;
|
||||
bool verbose = false;
|
||||
bool force = false;
|
||||
|
||||
@@ -71,6 +74,7 @@ main(int argc, char **argv)
|
||||
{"username", required_argument, NULL, 'U'},
|
||||
{"dest-dir", required_argument, NULL, 'D'},
|
||||
{"config-file", required_argument, NULL, 'f'},
|
||||
{"remote-user", required_argument, NULL, 'R'},
|
||||
{"force", no_argument, NULL, 'F'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{NULL, 0, NULL, 0}
|
||||
@@ -97,7 +101,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
|
||||
while ((c = getopt_long(argc, argv, "d:h:p:U:D:f:F:v", long_options, &optindex)) != -1)
|
||||
while ((c = getopt_long(argc, argv, "d:h:p:U:D:f:R:F:v", long_options, &optindex)) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
@@ -119,6 +123,9 @@ main(int argc, char **argv)
|
||||
case 'f':
|
||||
config_file = optarg;
|
||||
break;
|
||||
case 'R':
|
||||
remote_user = optarg;
|
||||
break;
|
||||
case 'F':
|
||||
force = true;
|
||||
break;
|
||||
@@ -262,7 +269,7 @@ do_master_register(void)
|
||||
{
|
||||
PGconn *conn;
|
||||
PGresult *res;
|
||||
char sqlquery[8192];
|
||||
char sqlquery[QUERY_STR_LEN];
|
||||
|
||||
char myClusterName[MAXLEN];
|
||||
int myLocalId = -1;
|
||||
@@ -440,7 +447,7 @@ do_standby_register(void)
|
||||
int master_id;
|
||||
|
||||
PGresult *res;
|
||||
char sqlquery[8192];
|
||||
char sqlquery[QUERY_STR_LEN];
|
||||
|
||||
char myClusterName[MAXLEN];
|
||||
int myLocalId = -1;
|
||||
@@ -566,7 +573,7 @@ do_standby_clone(void)
|
||||
{
|
||||
PGconn *conn;
|
||||
PGresult *res;
|
||||
char sqlquery[8192];
|
||||
char sqlquery[QUERY_STR_LEN];
|
||||
|
||||
int r = 0;
|
||||
int i;
|
||||
@@ -842,11 +849,11 @@ do_standby_clone(void)
|
||||
goto stop_backup;
|
||||
}
|
||||
|
||||
r = copy_remote_files(host, master_control_file, local_control_file, false);
|
||||
r = copy_remote_files(host, remote_user, master_control_file, local_control_file, false);
|
||||
if (r != 0)
|
||||
goto stop_backup;
|
||||
|
||||
r = copy_remote_files(host, master_data_directory, dest_dir, true);
|
||||
r = copy_remote_files(host, remote_user, master_data_directory, dest_dir, true);
|
||||
if (r != 0)
|
||||
goto stop_backup;
|
||||
|
||||
@@ -864,20 +871,20 @@ do_standby_clone(void)
|
||||
}
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
r = copy_remote_files(host, PQgetvalue(res, i, 0), PQgetvalue(res, i, 0), true);
|
||||
r = copy_remote_files(host, remote_user, PQgetvalue(res, i, 0), PQgetvalue(res, i, 0), true);
|
||||
if (r != 0)
|
||||
goto stop_backup;
|
||||
}
|
||||
|
||||
r = copy_remote_files(host, master_config_file, dest_dir, false);
|
||||
r = copy_remote_files(host, remote_user, master_config_file, dest_dir, false);
|
||||
if (r != 0)
|
||||
goto stop_backup;
|
||||
|
||||
r = copy_remote_files(host, master_hba_file, dest_dir, false);
|
||||
r = copy_remote_files(host, remote_user, master_hba_file, dest_dir, false);
|
||||
if (r != 0)
|
||||
goto stop_backup;
|
||||
|
||||
r = copy_remote_files(host, master_ident_file, dest_dir, false);
|
||||
r = copy_remote_files(host, remote_user, master_ident_file, dest_dir, false);
|
||||
if (r != 0)
|
||||
goto stop_backup;
|
||||
|
||||
@@ -911,14 +918,14 @@ stop_backup:
|
||||
return;
|
||||
|
||||
if (verbose)
|
||||
printf(_("%s requires primary to keep WAL files %s until at least %s"),
|
||||
printf(_("%s requires primary to keep WAL files %s until at least %s\n"),
|
||||
progname, first_wal_segment, last_wal_segment);
|
||||
|
||||
/* we need to create the pg_xlog sub directory too, i'm reusing a variable here */
|
||||
sprintf(local_control_file, "%s/pg_xlog", dest_dir);
|
||||
if (!create_directory(local_control_file))
|
||||
{
|
||||
fprintf(stderr, _("%s: couldn't create directory %s, you will need to do it manually... "),
|
||||
fprintf(stderr, _("%s: couldn't create directory %s, you will need to do it manually...\n"),
|
||||
progname, dest_dir);
|
||||
}
|
||||
|
||||
@@ -935,8 +942,8 @@ do_standby_promote(void)
|
||||
{
|
||||
PGconn *conn;
|
||||
PGresult *res;
|
||||
char sqlquery[8192];
|
||||
char script[8192];
|
||||
char sqlquery[QUERY_STR_LEN];
|
||||
char script[QUERY_STR_LEN];
|
||||
|
||||
char myClusterName[MAXLEN];
|
||||
int myLocalId = -1;
|
||||
@@ -1043,8 +1050,8 @@ do_standby_follow(void)
|
||||
{
|
||||
PGconn *conn;
|
||||
PGresult *res;
|
||||
char sqlquery[8192];
|
||||
char script[8192];
|
||||
char sqlquery[QUERY_STR_LEN];
|
||||
char script[QUERY_STR_LEN];
|
||||
|
||||
char myClusterName[MAXLEN];
|
||||
int myLocalId = -1;
|
||||
@@ -1180,18 +1187,21 @@ help(const char *progname)
|
||||
printf(_("Usage:\n"));
|
||||
printf(_(" %s [OPTIONS] master {register}\n"), progname);
|
||||
printf(_(" %s [OPTIONS] standby {register|clone|promote|follow}\n"), progname);
|
||||
printf(_("\nOptions:\n"));
|
||||
printf(_(" --help show this help, then exit\n"));
|
||||
printf(_(" --version output version information, then exit\n"));
|
||||
printf(_(" --verbose output verbose activity information\n"));
|
||||
printf(_("\nGeneral options:\n"));
|
||||
printf(_(" --help show this help, then exit\n"));
|
||||
printf(_(" --version output version information, then exit\n"));
|
||||
printf(_(" --verbose output verbose activity information\n"));
|
||||
printf(_("\nConnection options:\n"));
|
||||
printf(_(" -d, --dbname=DBNAME database to connect to\n"));
|
||||
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
|
||||
printf(_(" -p, --port=PORT database server port\n"));
|
||||
printf(_(" -U, --username=USERNAME user name to connect as\n"));
|
||||
printf(_(" -D, --data-dir=DIR directory where the files will be copied to\n"));
|
||||
printf(_(" -f, --config_file=PATH path to the configuration file\n"));
|
||||
printf(_("\n%s performs some tasks like clone a node, promote it "), progname);
|
||||
printf(_(" -d, --dbname=DBNAME database to connect to\n"));
|
||||
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
|
||||
printf(_(" -p, --port=PORT database server port\n"));
|
||||
printf(_(" -U, --username=USERNAME database user name to connect as\n"));
|
||||
printf(_("\nConfiguration options:\n"));
|
||||
printf(_(" -D, --data-dir=DIR local directory where the files will be copied to\n"));
|
||||
printf(_(" -f, --config_file=PATH path to the configuration file\n"));
|
||||
printf(_(" -R, --remote-user=USERNAME database server username for rsync\n"));
|
||||
|
||||
printf(_("\n%s performs some tasks like clone a node, promote it "), progname);
|
||||
printf(_("or making follow another node and then exits.\n"));
|
||||
printf(_("COMMANDS:\n"));
|
||||
printf(_(" master register - registers the master in a cluster\n"));
|
||||
@@ -1243,33 +1253,46 @@ create_recovery_file(const char *data_dir)
|
||||
|
||||
|
||||
static int
|
||||
copy_remote_files(char *host, char *remote_path, char *local_path, bool is_directory)
|
||||
copy_remote_files(char *host, char *remote_user, char *remote_path, char *local_path, bool is_directory)
|
||||
{
|
||||
char script[8192];
|
||||
char options[8192];
|
||||
char script[QUERY_STR_LEN];
|
||||
char options[QUERY_STR_LEN];
|
||||
char host_string[QUERY_STR_LEN];
|
||||
int r;
|
||||
|
||||
sprintf(options, "--archive --checksum --compress --progress --rsh=ssh");
|
||||
if (force)
|
||||
strcat(options, " --delete");
|
||||
|
||||
if (remote_user == NULL)
|
||||
{
|
||||
sprintf(host_string,"%s",host);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(host_string,"%s@%s",remote_user,host);
|
||||
}
|
||||
|
||||
if (is_directory)
|
||||
{
|
||||
strcat(options, " --exclude=pg_xlog* --exclude=pg_control --exclude=*.pid");
|
||||
sprintf(script, "rsync %s %s:%s/* %s",
|
||||
options, host, remote_path, local_path);
|
||||
options, host_string, remote_path, local_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(script, "rsync %s %s:%s %s/.",
|
||||
options, host, remote_path, local_path);
|
||||
options, host_string, remote_path, local_path);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf("rsync command line: '%s'\n",script);
|
||||
|
||||
r = system(script);
|
||||
|
||||
|
||||
if (r != 0)
|
||||
fprintf(stderr, _("Can't rsync from remote file or directory (%s:%s)\n"),
|
||||
host, remote_path);
|
||||
host_string, remote_path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user