PG_CPPFLAGS = -DFRONTEND -DDLSUFFIX=\"$(DLSUFFIX)\" -I$(srcdir) -I$(libpq_srcdir)
PG_LIBS = $(libpq_pgport)
-EXTRA_CLEAN = delete_old_cluster.sh log/ tmp_check/
+EXTRA_CLEAN = analyze_new_cluster.sh delete_old_cluster.sh log/ tmp_check/
ifdef USE_PGXS
PG_CONFIG = pg_config
if (sequence_script_file_name)
{
prep_status("Adjusting sequences");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/psql\" --echo-queries "
- "--set ON_ERROR_STOP=on "
- "--no-psqlrc --port %d --username \"%s\" "
- "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
- new_cluster.bindir, new_cluster.port, os_info.user,
- sequence_script_file_name, UTILITY_LOG_FILE);
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
+ new_cluster.bindir, cluster_conn_opts(&new_cluster),
+ sequence_script_file_name);
unlink(sequence_script_file_name);
check_ok();
}
* --binary-upgrade records the width of dropped columns in pg_class, and
* restores the frozenid's for databases and relations.
*/
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/pg_dumpall\" --port %d --username \"%s\" "
- "--schema-only --binary-upgrade %s > \"%s\" 2>> \"%s\""
- SYSTEMQUOTE, new_cluster.bindir, old_cluster.port, os_info.user,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/pg_dumpall\" %s --schema-only --binary-upgrade %s -f %s",
+ new_cluster.bindir, cluster_conn_opts(&old_cluster),
log_opts.verbose ? "--verbose" : "",
- ALL_DUMP_FILE, UTILITY_LOG_FILE);
+ ALL_DUMP_FILE);
check_ok();
}
/*
* exec_prog()
+ * Execute an external program with stdout/stderr redirected, and report
+ * errors
*
- * Formats a command from the given argument list and executes that
- * command. If the command executes, exec_prog() returns 1 otherwise
- * exec_prog() logs an error message and returns 0. Either way, the command
- * line to be executed is saved to the specified log file.
+ * Formats a command from the given argument list, logs it to the log file,
+ * and attempts to execute that command. If the command executes
+ * successfully, exec_prog() returns true.
*
- * If throw_error is TRUE, this function will throw a PG_FATAL error
- * instead of returning should an error occur. The command it appended
- * to log_file; opt_log_file is used in error messages.
+ * If the command fails, an error message is saved to the specified log_file.
+ * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
+ * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
+ * returns false.
*/
-int
-exec_prog(bool throw_error, bool is_priv, const char *log_file,
- const char *opt_log_file, const char *fmt,...)
+bool
+exec_prog(const char *log_file, const char *opt_log_file,
+ bool throw_error, const char *fmt,...)
{
- va_list args;
int result;
- int retval;
- char cmd[MAXPGPATH];
+ int written;
+#define MAXCMDLEN (2 * MAXPGPATH)
+ char cmd[MAXCMDLEN];
mode_t old_umask = 0;
FILE *log;
+ va_list ap;
- if (is_priv)
- old_umask = umask(S_IRWXG | S_IRWXO);
+ old_umask = umask(S_IRWXG | S_IRWXO);
- va_start(args, fmt);
- vsnprintf(cmd, MAXPGPATH, fmt, args);
- va_end(args);
+ written = strlcpy(cmd, SYSTEMQUOTE, strlen(SYSTEMQUOTE));
+ va_start(ap, fmt);
+ written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
+ va_end(ap);
+ if (written >= MAXCMDLEN)
+ pg_log(PG_FATAL, "command too long\n");
+ written += snprintf(cmd + written, MAXCMDLEN - written,
+ " >> \"%s\" 2>&1" SYSTEMQUOTE, log_file);
+ if (written >= MAXCMDLEN)
+ pg_log(PG_FATAL, "command too long\n");
if ((log = fopen_priv(log_file, "a+")) == NULL)
pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
pg_log(PG_VERBOSE, "%s\n", cmd);
fprintf(log, "command: %s\n", cmd);
+
/*
- * In Windows, we must close then reopen the log file so the file is
- * not open while the command is running, or we get a share violation.
+ * In Windows, we must close the log file at this point so the file is not
+ * open while the command is running, or we get a share violation.
*/
fclose(log);
result = system(cmd);
- if (is_priv)
- umask(old_umask);
+ umask(old_umask);
if (result != 0)
{
- char opt_string[MAXPGPATH];
-
- /* Create string for optional second log file */
- if (opt_log_file)
- snprintf(opt_string, sizeof(opt_string), " or \"%s\"", opt_log_file);
- else
- opt_string[0] = '\0';
-
report_status(PG_REPORT, "*failure*");
fflush(stdout);
pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
- pg_log(throw_error ? PG_FATAL : PG_REPORT,
- "Consult the last few lines of \"%s\"%s for\n"
- "the probable cause of the failure.\n",
- log_file, opt_string);
- retval = 1;
+ if (opt_log_file)
+ pg_log(throw_error ? PG_FATAL : PG_REPORT,
+ "Consult the last few lines of \"%s\" or \"%s\" for\n"
+ "the probable cause of the failure.\n",
+ log_file, opt_log_file);
+ else
+ pg_log(throw_error ? PG_FATAL : PG_REPORT,
+ "Consult the last few lines of \"%s\" for\n"
+ "the probable cause of the failure.\n",
+ log_file);
}
- else
- retval = 0;
if ((log = fopen_priv(log_file, "a+")) == NULL)
pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
fprintf(log, "\n\n");
fclose(log);
- return retval;
+ return result == 0;
}
/*
* linkAndUpdateFile()
*
- * Creates a symbolic link between the given relation files. We use
+ * Creates a hard link between the given relation files. We use
* this function to perform a true in-place update. If the on-disk
* format of the new cluster is bit-for-bit compatible with the on-disk
- * format of the old cluster, we can simply symlink each relation
+ * format of the old cluster, we can simply link each relation
* instead of copying the data from the old cluster to the new cluster.
*/
const char *
#include "postgres.h"
+#include "miscadmin.h"
+
#include "pg_upgrade.h"
#include <getopt_long.h>
check_ok();
}
+
+
+/*
+ * get_sock_dir
+ *
+ * Identify the socket directory to use for this cluster. If we're doing
+ * a live check (old cluster only), we need to find out where the postmaster
+ * is listening. Otherwise, we're going to put the socket into the current
+ * directory.
+ */
+void
+get_sock_dir(ClusterInfo *cluster, bool live_check)
+{
+#ifdef HAVE_UNIX_SOCKETS
+ if (!live_check)
+ {
+ /* Use the current directory for the socket */
+ cluster->sockdir = pg_malloc(MAXPGPATH);
+ if (!getcwd(cluster->sockdir, MAXPGPATH))
+ pg_log(PG_FATAL, "cannot find current directory\n");
+ }
+ else
+ {
+ /*
+ * If we are doing a live check, we will use the old cluster's Unix
+ * domain socket directory so we can connect to the live server.
+ */
+
+ /* sockdir was added to postmaster.pid in PG 9.1 */
+ if (GET_MAJOR_VERSION(cluster->major_version) >= 901)
+ {
+ char filename[MAXPGPATH];
+ FILE *fp;
+ int i;
+
+ snprintf(filename, sizeof(filename), "%s/postmaster.pid",
+ cluster->pgdata);
+ if ((fp = fopen(filename, "r")) == NULL)
+ pg_log(PG_FATAL, "Could not get socket directory of the old server\n");
+
+ cluster->sockdir = pg_malloc(MAXPGPATH);
+ for (i = 0; i < LOCK_FILE_LINE_SOCKET_DIR; i++)
+ if (fgets(cluster->sockdir, MAXPGPATH, fp) == NULL)
+ pg_log(PG_FATAL, "Could not get socket directory of the old server\n");
+
+ fclose(fp);
+
+ /* Remove trailing newline */
+ if (strchr(cluster->sockdir, '\n') != NULL)
+ *strchr(cluster->sockdir, '\n') = '\0';
+ }
+ else
+ {
+ /* Can't get live sockdir, so assume the default is OK. */
+ cluster->sockdir = NULL;
+ }
+ }
+#else /* !HAVE_UNIX_SOCKETS */
+ cluster->sockdir = NULL;
+#endif
+}
check_cluster_versions();
check_cluster_compatibility(live_check);
+ get_sock_dir(&old_cluster, live_check);
+ get_sock_dir(&new_cluster, false);
+
check_old_cluster(live_check, &sequence_script_file_name);
* because there is no need to have the schema load use new oids.
*/
prep_status("Setting next OID for new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" >> \"%s\" 2>&1"
- SYSTEMQUOTE,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/pg_resetxlog\" -o %u \"%s\"",
new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid,
- new_cluster.pgdata, UTILITY_LOG_FILE);
+ new_cluster.pgdata);
check_ok();
create_script_for_cluster_analyze(&analyze_script_file_name);
* --analyze so autovacuum doesn't update statistics later
*/
prep_status("Analyzing all rows in the new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
- "--all --analyze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
- new_cluster.bindir, new_cluster.port, os_info.user,
- log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/vacuumdb\" %s --all --analyze %s",
+ new_cluster.bindir, cluster_conn_opts(&new_cluster),
+ log_opts.verbose ? "--verbose" : "");
check_ok();
/*
* later.
*/
prep_status("Freezing all rows on the new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
- "--all --freeze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
- new_cluster.bindir, new_cluster.port, os_info.user,
- log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/vacuumdb\" %s --all --freeze %s",
+ new_cluster.bindir, cluster_conn_opts(&new_cluster),
+ log_opts.verbose ? "--verbose" : "");
check_ok();
get_pg_database_relfilenode(&new_cluster);
* support functions in template1 but pg_dumpall creates database using
* the template0 template.
*/
- exec_prog(true, true, RESTORE_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/psql\" --echo-queries "
- "--set ON_ERROR_STOP=on "
- /* --no-psqlrc prevents AUTOCOMMIT=off */
- "--no-psqlrc --port %d --username \"%s\" "
- "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
- new_cluster.bindir, new_cluster.port, os_info.user,
- GLOBALS_DUMP_FILE, RESTORE_LOG_FILE);
+ exec_prog(RESTORE_LOG_FILE, NULL, true,
+ "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
+ new_cluster.bindir, cluster_conn_opts(&new_cluster),
+ GLOBALS_DUMP_FILE);
check_ok();
/* we load this to get a current list of databases */
check_ok();
prep_status("Restoring database schema to new cluster");
- exec_prog(true, true, RESTORE_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/psql\" --echo-queries "
- "--set ON_ERROR_STOP=on "
- "--no-psqlrc --port %d --username \"%s\" "
- "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
- new_cluster.bindir, new_cluster.port, os_info.user,
- DB_DUMP_FILE, RESTORE_LOG_FILE);
+ exec_prog(RESTORE_LOG_FILE, NULL, true,
+ "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
+ new_cluster.bindir, cluster_conn_opts(&new_cluster),
+ DB_DUMP_FILE);
check_ok();
/* regenerate now that we have objects in the databases */
uninstall_support_functions_from_new_cluster();
}
-
+/*
+ * Delete the given subdirectory contents from the new cluster, and copy the
+ * files from the old cluster into it.
+ */
static void
-copy_clog_xlog_xid(void)
+copy_subdir_files(char *subdir)
{
- char old_clog_path[MAXPGPATH];
- char new_clog_path[MAXPGPATH];
+ char old_path[MAXPGPATH];
+ char new_path[MAXPGPATH];
- /* copy old commit logs to new data dir */
- prep_status("Deleting new commit clogs");
+ prep_status("Deleting files from new %s", subdir);
- snprintf(old_clog_path, sizeof(old_clog_path), "%s/pg_clog", old_cluster.pgdata);
- snprintf(new_clog_path, sizeof(new_clog_path), "%s/pg_clog", new_cluster.pgdata);
- if (!rmtree(new_clog_path, true))
- pg_log(PG_FATAL, "could not delete directory \"%s\"\n", new_clog_path);
+ snprintf(old_path, sizeof(old_path), "%s/%s", old_cluster.pgdata, subdir);
+ snprintf(new_path, sizeof(new_path), "%s/%s", new_cluster.pgdata, subdir);
+ if (!rmtree(new_path, true))
+ pg_log(PG_FATAL, "could not delete directory \"%s\"\n", new_path);
check_ok();
- prep_status("Copying old commit clogs to new server");
- exec_prog(true, false, UTILITY_LOG_FILE, NULL,
+ prep_status("Copying old %s to new server", subdir);
+
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
#ifndef WIN32
- SYSTEMQUOTE "%s \"%s\" \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
- "cp -Rf",
+ "cp -Rf \"%s\" \"%s\"",
#else
/* flags: everything, no confirm, quiet, overwrite read-only */
- SYSTEMQUOTE "%s \"%s\" \"%s\\\" >> \"%s\" 2>&1" SYSTEMQUOTE,
- "xcopy /e /y /q /r",
+ "xcopy /e /y /q /r \"%s\" \"%s\\\"",
#endif
- old_clog_path, new_clog_path, UTILITY_LOG_FILE);
+ old_path, new_path);
+
check_ok();
+}
+
+static void
+copy_clog_xlog_xid(void)
+{
+ /* copy old commit logs to new data dir */
+ copy_subdir_files("pg_clog");
/* set the next transaction id of the new cluster */
prep_status("Setting next transaction ID for new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE
- "\"%s/pg_resetxlog\" -f -x %u \"%s\" >> \"%s\" 2>&1"
- SYSTEMQUOTE, new_cluster.bindir,
- old_cluster.controldata.chkpnt_nxtxid,
- new_cluster.pgdata, UTILITY_LOG_FILE);
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/pg_resetxlog\" -f -x %u \"%s\"",
+ new_cluster.bindir, old_cluster.controldata.chkpnt_nxtxid,
+ new_cluster.pgdata);
check_ok();
/* now reset the wal archives in the new cluster */
prep_status("Resetting WAL archives");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE
- "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1"
- SYSTEMQUOTE, new_cluster.bindir,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\"", new_cluster.bindir,
old_cluster.controldata.chkpnt_tli,
old_cluster.controldata.logid,
old_cluster.controldata.nxtlogseg,
- new_cluster.pgdata, UTILITY_LOG_FILE);
+ new_cluster.pgdata);
check_ok();
}
char *bindir; /* pathname for cluster's executable directory */
char *pgopts; /* options to pass to the server, like pg_ctl
* -o */
+ char *sockdir; /* directory for Unix Domain socket, if any */
unsigned short port; /* port number where postmaster is waiting */
uint32 major_version; /* PG_VERSION of cluster */
char major_version_str[64]; /* string PG_VERSION of cluster */
/* exec.c */
-int
-exec_prog(bool throw_error, bool is_priv, const char *log_file,
- const char *opt_log_file, const char *cmd,...)
-__attribute__((format(PG_PRINTF_ATTRIBUTE, 5, 6)));
+#define EXEC_PSQL_ARGS "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"
+bool
+exec_prog(const char *log_file, const char *opt_log_file,
+ bool throw_error, const char *fmt,...)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 4, 5)));
void verify_directories(void);
bool is_server_running(const char *datadir);
void parseCommandLine(int argc, char *argv[]);
void adjust_data_dir(ClusterInfo *cluster);
+void get_sock_dir(ClusterInfo *cluster, bool live_check);
/* relfilenode.c */
executeQueryOrDie(PGconn *conn, const char *fmt,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
+char *cluster_conn_opts(ClusterInfo *cluster);
+
void start_postmaster(ClusterInfo *cluster);
void stop_postmaster(bool fast);
uint32 get_major_server_version(ClusterInfo *cluster);
/*
* get_db_conn()
*
- * get database connection
+ * get database connection, using named database + standard params for cluster
*/
static PGconn *
get_db_conn(ClusterInfo *cluster, const char *db_name)
{
- char conn_opts[MAXPGPATH];
+ char conn_opts[2 * NAMEDATALEN + MAXPGPATH + 100];
- snprintf(conn_opts, sizeof(conn_opts),
- "dbname = '%s' user = '%s' port = %d", db_name, os_info.user,
- cluster->port);
+ if (cluster->sockdir)
+ snprintf(conn_opts, sizeof(conn_opts),
+ "dbname = '%s' user = '%s' host = '%s' port = %d",
+ db_name, os_info.user, cluster->sockdir, cluster->port);
+ else
+ snprintf(conn_opts, sizeof(conn_opts),
+ "dbname = '%s' user = '%s' port = %d",
+ db_name, os_info.user, cluster->port);
return PQconnectdb(conn_opts);
}
+/*
+ * cluster_conn_opts()
+ *
+ * Return standard command-line options for connecting to this cluster when
+ * using psql, pg_dump, etc. Ideally this would match what get_db_conn()
+ * sets, but the utilities we need aren't very consistent about the treatment
+ * of database name options, so we leave that out.
+ *
+ * Note result is in static storage, so use it right away.
+ */
+char *
+cluster_conn_opts(ClusterInfo *cluster)
+{
+ static char conn_opts[MAXPGPATH + NAMEDATALEN + 100];
+
+ if (cluster->sockdir)
+ snprintf(conn_opts, sizeof(conn_opts),
+ "--host \"%s\" --port %d --username \"%s\"",
+ cluster->sockdir, cluster->port, os_info.user);
+ else
+ snprintf(conn_opts, sizeof(conn_opts),
+ "--port %d --username \"%s\"",
+ cluster->port, os_info.user);
+
+ return conn_opts;
+}
+
+
/*
* executeQueryOrDie()
*
void
start_postmaster(ClusterInfo *cluster)
{
- char cmd[MAXPGPATH];
+ char cmd[MAXPGPATH * 4 + 1000];
PGconn *conn;
bool exit_hook_registered = false;
- int pg_ctl_return = 0;
+ bool pg_ctl_return = false;
+ char socket_string[MAXPGPATH + 200];
if (!exit_hook_registered)
{
exit_hook_registered = true;
}
+ socket_string[0] = '\0';
+
+#ifdef HAVE_UNIX_SOCKETS
+ /* prevent TCP/IP connections, restrict socket access */
+ strcat(socket_string,
+ " -c listen_addresses='' -c unix_socket_permissions=0700");
+
+ /* Have a sockdir? Tell the postmaster. */
+ if (cluster->sockdir)
+ snprintf(socket_string + strlen(socket_string),
+ sizeof(socket_string) - strlen(socket_string),
+ " -c %s='%s'",
+ (GET_MAJOR_VERSION(cluster->major_version) < 903) ?
+ "unix_socket_directory" : "unix_socket_directories",
+ cluster->sockdir);
+#endif
+
/*
* Using autovacuum=off disables cleanup vacuum and analyze, but freeze
* vacuums can still happen, so we set autovacuum_freeze_max_age to its
* not touch them.
*/
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" "
- "-o \"-p %d %s %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE,
+ "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d %s %s%s\" start",
cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
(cluster->controldata.cat_ver >=
BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
"-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
- cluster->pgopts ? cluster->pgopts : "", SERVER_START_LOG_FILE);
+ cluster->pgopts ? cluster->pgopts : "", socket_string);
/*
* Don't throw an error right away, let connecting throw the error because
* it might supply a reason for the failure.
*/
- pg_ctl_return = exec_prog(false, true, SERVER_START_LOG_FILE,
- /* pass both file names if the differ */
- (strcmp(SERVER_LOG_FILE, SERVER_START_LOG_FILE) != 0) ?
+ pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
+ /* pass both file names if they differ */
+ (strcmp(SERVER_LOG_FILE,
+ SERVER_START_LOG_FILE) != 0) ?
SERVER_LOG_FILE : NULL,
+ false,
"%s", cmd);
/* Check to see if we can connect to the server; if not, report it. */
PQerrorMessage(conn));
if (conn)
PQfinish(conn);
- pg_log(PG_FATAL, "could not connect to %s postmaster started with the command: %s\n",
+ pg_log(PG_FATAL, "could not connect to %s postmaster started with the command:\n"
+ "%s\n",
CLUSTER_NAME(cluster), cmd);
}
PQfinish(conn);
/* If the connection didn't fail, fail now */
- if (pg_ctl_return != 0)
+ if (!pg_ctl_return)
pg_log(PG_FATAL, "pg_ctl failed to start the %s server, or connection failed\n",
CLUSTER_NAME(cluster));
void
stop_postmaster(bool fast)
{
- char cmd[MAXPGPATH];
ClusterInfo *cluster;
if (os_info.running_cluster == &old_cluster)
else
return; /* no cluster running */
- snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" "
- "%s stop >> \"%s\" 2>&1" SYSTEMQUOTE,
- cluster->bindir, cluster->pgconfig,
- cluster->pgopts ? cluster->pgopts : "",
- fast ? "-m fast" : "", SERVER_STOP_LOG_FILE);
-
- exec_prog(fast ? false : true, true, SERVER_STOP_LOG_FILE, NULL, "%s", cmd);
+ exec_prog(SERVER_STOP_LOG_FILE, NULL, !fast,
+ "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
+ cluster->bindir, cluster->pgconfig,
+ cluster->pgopts ? cluster->pgopts : "",
+ fast ? "-m fast" : "");
os_info.running_cluster = NULL;
}
pg_upgrade -d "${PGDATA}.old" -D "${PGDATA}" -b "$oldbindir" -B "$bindir"
pg_ctl start -l "$logdir/postmaster2.log" -w
+sh ./analyze_new_cluster.sh
pg_dumpall >"$temp_root"/dump2.sql || pg_dumpall2_status=$?
pg_ctl -m fast stop
if [ -n "$pg_dumpall2_status" ]; then
exit 1
fi
+sh ./delete_old_cluster.sh
+
if diff -q "$temp_root"/dump1.sql "$temp_root"/dump2.sql; then
echo PASSED
exit 0
Obviously, no one should be accessing the clusters during the
upgrade. <application>pg_upgrade</> defaults to running servers
on port 50432 to avoid unintended client connections.
- You can use the same port numbers for both clusters because the
- old and new clusters will not be running at the same time.
+ You can use the same port number for both clusters when doing an
+ upgrade because the old and new clusters will not be running at the
+ same time. However, when checking an old running server, the old
+ and new port numbers must be different.
</para>
<para>
<literal>-d /real-data-directory -o '-D /configuration-directory'</>.
</para>
+ <para>
+ If doing <option>--check</> with a running old server of a pre-9.1 version,
+ and the old server is using a Unix-domain socket directory that is
+ different from the default built into the new <productname>PostgreSQL</>
+ installation, set <envar>PGHOST</> to point to the socket location of the
+ old server. (This is not relevant on Windows.)
+ </para>
+
<para>
A Log-Shipping Standby Server (<xref linkend="warm-standby">) cannot
be upgraded because the server must allow writes. The simplest way