6 * Copyright (c) 2010-2021, PostgreSQL Global Development Group
7 * src/bin/pg_upgrade/option.c
10 #include "postgres_fe.h"
17 #include "common/string.h"
18 #include "getopt_long.h"
19 #include "pg_upgrade.h"
20 #include "utils/pidfile.h"
22 static void usage(void);
23 static void check_required_directory(char **dirpath
,
24 const char *envVarName
, bool useCwd
,
25 const char *cmdLineOption
, const char *description
,
27 #define FIX_DEFAULT_READ_ONLY "-c default_transaction_read_only=false"
36 * Parses the command line (argc, argv[]) and loads structures
39 parseCommandLine(int argc
, char *argv
[])
41 static struct option long_options
[] = {
42 {"old-datadir", required_argument
, NULL
, 'd'},
43 {"new-datadir", required_argument
, NULL
, 'D'},
44 {"old-bindir", required_argument
, NULL
, 'b'},
45 {"new-bindir", required_argument
, NULL
, 'B'},
46 {"old-options", required_argument
, NULL
, 'o'},
47 {"new-options", required_argument
, NULL
, 'O'},
48 {"old-port", required_argument
, NULL
, 'p'},
49 {"new-port", required_argument
, NULL
, 'P'},
51 {"username", required_argument
, NULL
, 'U'},
52 {"check", no_argument
, NULL
, 'c'},
53 {"link", no_argument
, NULL
, 'k'},
54 {"retain", no_argument
, NULL
, 'r'},
55 {"jobs", required_argument
, NULL
, 'j'},
56 {"socketdir", required_argument
, NULL
, 's'},
57 {"verbose", no_argument
, NULL
, 'v'},
58 {"clone", no_argument
, NULL
, 1},
62 int option
; /* Command line option */
63 int optindex
= 0; /* used by getopt_long */
64 int os_user_effective_id
;
67 time_t run_time
= time(NULL
);
69 user_opts
.transfer_mode
= TRANSFER_MODE_COPY
;
71 os_info
.progname
= get_progname(argv
[0]);
73 /* Process libpq env. variables; load values here for usage() output */
74 old_cluster
.port
= getenv("PGPORTOLD") ? atoi(getenv("PGPORTOLD")) : DEF_PGUPORT
;
75 new_cluster
.port
= getenv("PGPORTNEW") ? atoi(getenv("PGPORTNEW")) : DEF_PGUPORT
;
77 os_user_effective_id
= get_user_info(&os_info
.user
);
78 /* we override just the database user name; we got the OS id above */
81 pg_free(os_info
.user
);
82 /* must save value, getenv()'s pointer is not stable */
83 os_info
.user
= pg_strdup(getenv("PGUSER"));
88 if (strcmp(argv
[1], "--help") == 0 || strcmp(argv
[1], "-?") == 0)
93 if (strcmp(argv
[1], "--version") == 0 || strcmp(argv
[1], "-V") == 0)
95 puts("pg_upgrade (PostgreSQL) " PG_VERSION
);
100 /* Allow help and version to be run as root, so do the test here. */
101 if (os_user_effective_id
== 0)
102 pg_fatal("%s: cannot be run as root\n", os_info
.progname
);
104 while ((option
= getopt_long(argc
, argv
, "d:D:b:B:cj:ko:O:p:P:rs:U:v",
105 long_options
, &optindex
)) != -1)
110 old_cluster
.bindir
= pg_strdup(optarg
);
114 new_cluster
.bindir
= pg_strdup(optarg
);
118 user_opts
.check
= true;
122 old_cluster
.pgdata
= pg_strdup(optarg
);
126 new_cluster
.pgdata
= pg_strdup(optarg
);
130 user_opts
.jobs
= atoi(optarg
);
134 user_opts
.transfer_mode
= TRANSFER_MODE_LINK
;
139 if (!old_cluster
.pgopts
)
140 old_cluster
.pgopts
= pg_strdup(optarg
);
143 char *old_pgopts
= old_cluster
.pgopts
;
145 old_cluster
.pgopts
= psprintf("%s %s", old_pgopts
, optarg
);
152 if (!new_cluster
.pgopts
)
153 new_cluster
.pgopts
= pg_strdup(optarg
);
156 char *new_pgopts
= new_cluster
.pgopts
;
158 new_cluster
.pgopts
= psprintf("%s %s", new_pgopts
, optarg
);
164 * Someday, the port number option could be removed and passed
165 * using -o/-O, but that requires postmaster -C to be
166 * supported on all old/new versions (added in PG 9.2).
169 if ((old_cluster
.port
= atoi(optarg
)) <= 0)
170 pg_fatal("invalid old port number\n");
174 if ((new_cluster
.port
= atoi(optarg
)) <= 0)
175 pg_fatal("invalid new port number\n");
179 log_opts
.retain
= true;
183 user_opts
.socketdir
= pg_strdup(optarg
);
187 pg_free(os_info
.user
);
188 os_info
.user
= pg_strdup(optarg
);
189 os_info
.user_specified
= true;
192 * Push the user name into the environment so pre-9.1
193 * pg_ctl/libpq uses it.
195 setenv("PGUSER", os_info
.user
, 1);
199 log_opts
.verbose
= true;
203 user_opts
.transfer_mode
= TRANSFER_MODE_CLONE
;
207 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
214 pg_fatal("too many command-line arguments (first is \"%s\")\n", argv
[optind
]);
216 if ((log_opts
.internal
= fopen_priv(INTERNAL_LOG_FILE
, "a")) == NULL
)
217 pg_fatal("could not open log file \"%s\": %m\n", INTERNAL_LOG_FILE
);
219 if (log_opts
.verbose
)
220 pg_log(PG_REPORT
, "Running in verbose mode\n");
222 /* label start of upgrade in logfiles */
223 for (filename
= output_files
; *filename
!= NULL
; filename
++)
225 if ((fp
= fopen_priv(*filename
, "a")) == NULL
)
226 pg_fatal("could not write to log file \"%s\": %m\n", *filename
);
228 /* Start with newline because we might be appending to a file. */
230 "-----------------------------------------------------------------\n"
231 " pg_upgrade run on %s"
232 "-----------------------------------------------------------------\n\n",
237 /* Turn off read-only mode; add prefix to PGOPTIONS? */
238 if (getenv("PGOPTIONS"))
240 char *pgoptions
= psprintf("%s %s", FIX_DEFAULT_READ_ONLY
,
241 getenv("PGOPTIONS"));
243 setenv("PGOPTIONS", pgoptions
, 1);
247 setenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY
, 1);
249 /* Get values from env if not already set */
250 check_required_directory(&old_cluster
.bindir
, "PGBINOLD", false,
251 "-b", _("old cluster binaries reside"), false);
252 check_required_directory(&new_cluster
.bindir
, "PGBINNEW", false,
253 "-B", _("new cluster binaries reside"), true);
254 check_required_directory(&old_cluster
.pgdata
, "PGDATAOLD", false,
255 "-d", _("old cluster data resides"), false);
256 check_required_directory(&new_cluster
.pgdata
, "PGDATANEW", false,
257 "-D", _("new cluster data resides"), false);
258 check_required_directory(&user_opts
.socketdir
, "PGSOCKETDIR", true,
259 "-s", _("sockets will be created"), false);
264 * On Windows, initdb --sync-only will fail with a "Permission denied"
265 * error on file pg_upgrade_utility.log if pg_upgrade is run inside the
266 * new cluster directory, so we do a check here.
270 new_cluster_pgdata
[MAXPGPATH
];
272 strlcpy(new_cluster_pgdata
, new_cluster
.pgdata
, MAXPGPATH
);
273 canonicalize_path(new_cluster_pgdata
);
275 if (!getcwd(cwd
, MAXPGPATH
))
276 pg_fatal("could not determine current directory\n");
277 canonicalize_path(cwd
);
278 if (path_is_prefix_of_path(new_cluster_pgdata
, cwd
))
279 pg_fatal("cannot run pg_upgrade from inside the new cluster data directory on Windows\n");
288 printf(_("pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n\n"));
289 printf(_("Usage:\n"));
290 printf(_(" pg_upgrade [OPTION]...\n\n"));
291 printf(_("Options:\n"));
292 printf(_(" -b, --old-bindir=BINDIR old cluster executable directory\n"));
293 printf(_(" -B, --new-bindir=BINDIR new cluster executable directory (default\n"
294 " same directory as pg_upgrade)\n"));
295 printf(_(" -c, --check check clusters only, don't change any data\n"));
296 printf(_(" -d, --old-datadir=DATADIR old cluster data directory\n"));
297 printf(_(" -D, --new-datadir=DATADIR new cluster data directory\n"));
298 printf(_(" -j, --jobs=NUM number of simultaneous processes or threads to use\n"));
299 printf(_(" -k, --link link instead of copying files to new cluster\n"));
300 printf(_(" -o, --old-options=OPTIONS old cluster options to pass to the server\n"));
301 printf(_(" -O, --new-options=OPTIONS new cluster options to pass to the server\n"));
302 printf(_(" -p, --old-port=PORT old cluster port number (default %d)\n"), old_cluster
.port
);
303 printf(_(" -P, --new-port=PORT new cluster port number (default %d)\n"), new_cluster
.port
);
304 printf(_(" -r, --retain retain SQL and log files after success\n"));
305 printf(_(" -s, --socketdir=DIR socket directory to use (default current dir.)\n"));
306 printf(_(" -U, --username=NAME cluster superuser (default \"%s\")\n"), os_info
.user
);
307 printf(_(" -v, --verbose enable verbose internal logging\n"));
308 printf(_(" -V, --version display version information, then exit\n"));
309 printf(_(" --clone clone instead of copying files to new cluster\n"));
310 printf(_(" -?, --help show this help, then exit\n"));
312 "Before running pg_upgrade you must:\n"
313 " create a new database cluster (using the new version of initdb)\n"
314 " shutdown the postmaster servicing the old cluster\n"
315 " shutdown the postmaster servicing the new cluster\n"));
317 "When you run pg_upgrade, you must provide the following information:\n"
318 " the data directory for the old cluster (-d DATADIR)\n"
319 " the data directory for the new cluster (-D DATADIR)\n"
320 " the \"bin\" directory for the old version (-b BINDIR)\n"
321 " the \"bin\" directory for the new version (-B BINDIR)\n"));
324 " pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B newCluster/bin\n"
327 printf(_(" $ export PGDATAOLD=oldCluster/data\n"
328 " $ export PGDATANEW=newCluster/data\n"
329 " $ export PGBINOLD=oldCluster/bin\n"
330 " $ export PGBINNEW=newCluster/bin\n"
333 printf(_(" C:\\> set PGDATAOLD=oldCluster/data\n"
334 " C:\\> set PGDATANEW=newCluster/data\n"
335 " C:\\> set PGBINOLD=oldCluster/bin\n"
336 " C:\\> set PGBINNEW=newCluster/bin\n"
337 " C:\\> pg_upgrade\n"));
339 printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT
);
340 printf(_("%s home page: <%s>\n"), PACKAGE_NAME
, PACKAGE_URL
);
345 * check_required_directory()
347 * Checks a directory option.
348 * dirpath - the directory name supplied on the command line, or NULL
349 * envVarName - the name of an environment variable to get if dirpath is NULL
350 * useCwd - true if OK to default to CWD
351 * cmdLineOption - the command line option for this directory
352 * description - a description of this directory option
353 * missingOk - true if OK that both dirpath and envVarName are not existing
355 * We use the last two arguments to construct a meaningful error message if the
356 * user hasn't provided the required directory name.
359 check_required_directory(char **dirpath
, const char *envVarName
, bool useCwd
,
360 const char *cmdLineOption
, const char *description
,
363 if (*dirpath
== NULL
|| strlen(*dirpath
) == 0)
367 if ((envVar
= getenv(envVarName
)) && strlen(envVar
))
368 *dirpath
= pg_strdup(envVar
);
373 if (!getcwd(cwd
, MAXPGPATH
))
374 pg_fatal("could not determine current directory\n");
375 *dirpath
= pg_strdup(cwd
);
380 pg_fatal("You must identify the directory where the %s.\n"
381 "Please use the %s command-line option or the %s environment variable.\n",
382 description
, cmdLineOption
, envVarName
);
386 * Clean up the path, in particular trimming any trailing path separators,
387 * because we construct paths by appending to this path.
389 canonicalize_path(*dirpath
);
395 * If a configuration-only directory was specified, find the real data dir
396 * by querying the running server. This has limited checking because we
397 * can't check for a running server because we can't find postmaster.pid.
399 * On entry, cluster->pgdata has been set from command line or env variable,
400 * but cluster->pgconfig isn't set. We fill both variables with corrected
404 adjust_data_dir(ClusterInfo
*cluster
)
406 char filename
[MAXPGPATH
];
408 cmd_output
[MAX_STRING
];
412 /* Initially assume config dir and data dir are the same */
413 cluster
->pgconfig
= pg_strdup(cluster
->pgdata
);
415 /* If there is no postgresql.conf, it can't be a config-only dir */
416 snprintf(filename
, sizeof(filename
), "%s/postgresql.conf", cluster
->pgconfig
);
417 if ((fp
= fopen(filename
, "r")) == NULL
)
421 /* If PG_VERSION exists, it can't be a config-only dir */
422 snprintf(filename
, sizeof(filename
), "%s/PG_VERSION", cluster
->pgconfig
);
423 if ((fp
= fopen(filename
, "r")) != NULL
)
429 /* Must be a configuration directory, so find the real data directory. */
431 if (cluster
== &old_cluster
)
432 prep_status("Finding the real data directory for the source cluster");
434 prep_status("Finding the real data directory for the target cluster");
437 * We don't have a data directory yet, so we can't check the PG version,
438 * so this might fail --- only works for PG 9.2+. If this fails,
439 * pg_upgrade will fail anyway because the data files will not be found.
441 snprintf(cmd
, sizeof(cmd
), "\"%s/postgres\" -D \"%s\" -C data_directory",
442 cluster
->bindir
, cluster
->pgconfig
);
444 if ((output
= popen(cmd
, "r")) == NULL
||
445 fgets(cmd_output
, sizeof(cmd_output
), output
) == NULL
)
446 pg_fatal("could not get data directory using %s: %s\n",
447 cmd
, strerror(errno
));
451 /* strip trailing newline and carriage return */
452 (void) pg_strip_crlf(cmd_output
);
454 cluster
->pgdata
= pg_strdup(cmd_output
);
463 * Identify the socket directory to use for this cluster. If we're doing
464 * a live check (old cluster only), we need to find out where the postmaster
465 * is listening. Otherwise, we're going to put the socket into the current
469 get_sock_dir(ClusterInfo
*cluster
, bool live_check
)
471 #if defined(HAVE_UNIX_SOCKETS) && !defined(WIN32)
474 * sockdir and port were added to postmaster.pid in PG 9.1. Pre-9.1 cannot
475 * process pg_ctl -w for sockets in non-default locations.
477 if (GET_MAJOR_VERSION(cluster
->major_version
) >= 901)
480 cluster
->sockdir
= user_opts
.socketdir
;
484 * If we are doing a live check, we will use the old cluster's
485 * Unix domain socket directory so we can connect to the live
488 unsigned short orig_port
= cluster
->port
;
489 char filename
[MAXPGPATH
],
494 snprintf(filename
, sizeof(filename
), "%s/postmaster.pid",
496 if ((fp
= fopen(filename
, "r")) == NULL
)
497 pg_fatal("could not open file \"%s\": %s\n",
498 filename
, strerror(errno
));
501 lineno
<= Max(LOCK_FILE_LINE_PORT
, LOCK_FILE_LINE_SOCKET_DIR
);
504 if (fgets(line
, sizeof(line
), fp
) == NULL
)
505 pg_fatal("could not read line %d from file \"%s\": %s\n",
506 lineno
, filename
, strerror(errno
));
508 /* potentially overwrite user-supplied value */
509 if (lineno
== LOCK_FILE_LINE_PORT
)
510 sscanf(line
, "%hu", &old_cluster
.port
);
511 if (lineno
== LOCK_FILE_LINE_SOCKET_DIR
)
513 /* strip trailing newline and carriage return */
514 cluster
->sockdir
= pg_strdup(line
);
515 (void) pg_strip_crlf(cluster
->sockdir
);
520 /* warn of port number correction */
521 if (orig_port
!= DEF_PGUPORT
&& old_cluster
.port
!= orig_port
)
522 pg_log(PG_WARNING
, "user-supplied old port number %hu corrected to %hu\n",
523 orig_port
, cluster
->port
);
529 * Can't get sockdir and pg_ctl -w can't use a non-default, use
532 cluster
->sockdir
= NULL
;
533 #else /* !HAVE_UNIX_SOCKETS || WIN32 */
534 cluster
->sockdir
= NULL
;