From a37b001b8048a17f40a59cb8e26c593a6a21e500 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 10 Dec 2009 06:32:28 +0000 Subject: [PATCH] Add init[db] option to pg_ctl pg_ctl gets a new mode that runs initdb. Adjust the documentation a bit to not assume that initdb is the only way to run database cluster initialization. But don't replace initdb as the canonical way. Author: Zdenek Kotala --- doc/src/sgml/config.sgml | 8 +-- doc/src/sgml/manage-ag.sgml | 12 ++-- doc/src/sgml/ref/initdb.sgml | 12 +++- doc/src/sgml/ref/pg_ctl-ref.sgml | 36 ++++++++-- doc/src/sgml/runtime.sgml | 16 ++++- doc/src/sgml/xfunc.sgml | 5 +- src/bin/pg_ctl/pg_ctl.c | 120 ++++++++++++++++++++----------- 7 files changed, 149 insertions(+), 60 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index d5f55e0539b..1fb32c8de39 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,4 +1,4 @@ - + Server Configuration @@ -54,9 +54,9 @@ One way to set these parameters is to edit the file postgresql.confpostgresql.conf, - which is normally kept in the data directory. (initdb - installs a default copy there.) An example of what this file might look - like is: + which is normally kept in the data directory. (A default copy is + installed there when the database cluster directory is + initialized.) An example of what this file might look like is: # This is a comment log_connections = yes diff --git a/doc/src/sgml/manage-ag.sgml b/doc/src/sgml/manage-ag.sgml index a2c196f1dd9..8712e5c9788 100644 --- a/doc/src/sgml/manage-ag.sgml +++ b/doc/src/sgml/manage-ag.sgml @@ -1,4 +1,4 @@ - + Managing Databases @@ -119,8 +119,8 @@ CREATE DATABASE name; A second database, template1,template1 - is also created by - initdb. Whenever a new database is created within the + is also created during database cluster initialization. Whenever a + new database is created within the cluster, template1 is essentially cloned. This means that any changes you make in template1 are propagated to all subsequently created databases. Therefore it is @@ -196,7 +196,8 @@ createdb -O rolename dbname template1, that is, only the standard objects predefined by your version of PostgreSQL. template0 - should never be changed after initdb. By instructing + should never be changed after the database cluster has been + initialized. By instructing CREATE DATABASE to copy template0 instead of template1, you can create a virgin user database that contains none of the site-local additions in @@ -453,7 +454,8 @@ CREATE TABLE foo(i int); - Two tablespaces are automatically created by initdb. The + Two tablespaces are automatically created when the database cluster + is initialized. The pg_global tablespace is used for shared system catalogs. The pg_default tablespace is the default tablespace of the template1 and template0 databases (and, therefore, diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml index 110c21eb8c5..875a0e5eae2 100644 --- a/doc/src/sgml/ref/initdb.sgml +++ b/doc/src/sgml/ref/initdb.sgml @@ -1,5 +1,5 @@ @@ -309,10 +309,20 @@ PostgreSQL documentation + + Notes + + + initdb can also be invoked via + pg_ctl initdb. + + + See Also + diff --git a/doc/src/sgml/ref/pg_ctl-ref.sgml b/doc/src/sgml/ref/pg_ctl-ref.sgml index 638f3f18714..16d93736349 100644 --- a/doc/src/sgml/ref/pg_ctl-ref.sgml +++ b/doc/src/sgml/ref/pg_ctl-ref.sgml @@ -1,5 +1,5 @@ @@ -12,7 +12,7 @@ PostgreSQL documentation pg_ctl - start, stop, or restart a PostgreSQL server + initialize, start, stop, or restart a PostgreSQL server @@ -22,6 +22,13 @@ PostgreSQL documentation + pg_ctl + init[db] + -s + -D datadir + -o options + + pg_ctl start -w @@ -105,7 +112,8 @@ PostgreSQL documentation Description - pg_ctl is a utility for starting, + pg_ctl is a utility for initializing a + PostgreSQL database cluster, starting, stopping, or restarting the PostgreSQL backend server (), or displaying the status of a running server. Although the server can be started @@ -115,6 +123,15 @@ PostgreSQL documentation controlled shutdown. + + The or mode creates a + new + PostgreSQL database cluster. A database + cluster is a collection of databases that are managed by a single + server instance. This mode invokes the initdb + command. See for details. + + In mode, a new server is launched. The server is started in the background, and standard input is attached to @@ -263,6 +280,12 @@ PostgreSQL documentation option unless you are doing something unusual and get errors that the postgres executable was not found. + + + In init mode, this option analogously + specifies the location of the initdb + executable. + @@ -542,9 +565,10 @@ Command line was: See Also - - - + + + + diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 6cd5b7ce605..a68ba64dac5 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,4 +1,4 @@ - + Server Setup and Operation @@ -93,6 +93,20 @@ + + Alternatively, you can run initdb via + the + programpg_ctl like so: + +$ pg_ctl -D /usr/local/pgsql/data initdb + + This may be more intuitive if you are + using pg_ctl for starting and stopping the + server (see ), so + that pg_ctl would be the sole command you use + for managing the database server instance. + + initdb will attempt to create the directory you specify if it does not already exist. It is likely that it will not diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index b0ef51c7df6..d8caa9893d6 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,4 +1,4 @@ - + User-Defined Functions @@ -1353,7 +1353,8 @@ CREATE FUNCTION test(int, int) RETURNS int Normally, all internal functions present in the - server are declared during the initialization of the database cluster (initdb), + server are declared during the initialization of the database cluster + (see ), but a user could use CREATE FUNCTION to create additional alias names for an internal function. Internal functions are declared in CREATE FUNCTION diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 1942db9f13a..1e874a700f7 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -4,7 +4,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.115 2009/11/14 15:39:36 mha Exp $ + * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.116 2009/12/10 06:32:28 petere Exp $ * *------------------------------------------------------------------------- */ @@ -57,6 +57,7 @@ typedef enum typedef enum { NO_COMMAND = 0, + INIT_COMMAND, START_COMMAND, STOP_COMMAND, RESTART_COMMAND, @@ -82,7 +83,7 @@ static char *pgdata_opt = NULL; static char *post_opts = NULL; static const char *progname; static char *log_file = NULL; -static char *postgres_path = NULL; +static char *exec_path = NULL; static char *register_servicename = "PostgreSQL"; /* FIXME: + version ID? */ static char *register_username = NULL; static char *register_password = NULL; @@ -100,6 +101,7 @@ static void do_advice(void); static void do_help(void); static void set_mode(char *modeopt); static void set_sig(char *signame); +static void do_init(void); static void do_start(void); static void do_stop(void); static void do_restart(void); @@ -358,11 +360,11 @@ start_postmaster(void) */ if (log_file != NULL) snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &" SYSTEMQUOTE, - postgres_path, pgdata_opt, post_opts, + exec_path, pgdata_opt, post_opts, DEVNULL, log_file); else snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1 &" SYSTEMQUOTE, - postgres_path, pgdata_opt, post_opts, DEVNULL); + exec_path, pgdata_opt, post_opts, DEVNULL); return system(cmd); #else /* WIN32 */ @@ -376,10 +378,10 @@ start_postmaster(void) if (log_file != NULL) snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE, - postgres_path, pgdata_opt, post_opts, DEVNULL, log_file); + exec_path, pgdata_opt, post_opts, DEVNULL, log_file); else snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1" SYSTEMQUOTE, - postgres_path, pgdata_opt, post_opts, DEVNULL); + exec_path, pgdata_opt, post_opts, DEVNULL); if (!CreateRestrictedProcess(cmd, &pi, false)) return GetLastError(); @@ -607,13 +609,70 @@ read_post_opts(void) * name */ post_opts = arg1 + 1; /* point past whitespace */ } - if (postgres_path == NULL) - postgres_path = optline; + if (exec_path == NULL) + exec_path = optline; } } } } +static char * +find_other_exec_or_die(const char *argv0, const char *target, const char *versionstr) +{ + int ret; + char *found_path; + + found_path = pg_malloc(MAXPGPATH); + + if ((ret = find_other_exec(argv0, target, versionstr, found_path)) < 0) + { + char full_path[MAXPGPATH]; + + if (find_my_exec(argv0, full_path) < 0) + strlcpy(full_path, progname, sizeof(full_path)); + + if (ret == -1) + write_stderr(_("The program \"%s\" is needed by %s " + "but was not found in the\n" + "same directory as \"%s\".\n" + "Check your installation.\n"), + target, progname, full_path); + else + write_stderr(_("The program \"%s\" was found by \"%s\"\n" + "but was not the same version as %s.\n" + "Check your installation.\n"), + target, full_path, progname); + exit(1); + } + + return found_path; +} + +static void +do_init(void) +{ + char cmd[MAXPGPATH]; + + if (exec_path == NULL) + exec_path = find_other_exec_or_die(argv0, "initdb", "initdb (PostgreSQL) " PG_VERSION "\n"); + + if (post_opts == NULL) + post_opts = ""; + + if (!silent_mode) + snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s" SYSTEMQUOTE, + exec_path, pgdata_opt, post_opts); + else + snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s > \"%s\"" SYSTEMQUOTE, + exec_path, pgdata_opt, post_opts, DEVNULL); + + if (system(cmd) != 0) + { + write_stderr(_("%s: database system initialization failed\n"), progname); + exit(1); + } +} + static void do_start(void) { @@ -636,36 +695,8 @@ do_start(void) if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL) pgdata_opt = ""; - if (postgres_path == NULL) - { - char *postmaster_path; - int ret; - - postmaster_path = pg_malloc(MAXPGPATH); - - if ((ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR, - postmaster_path)) < 0) - { - char full_path[MAXPGPATH]; - - if (find_my_exec(argv0, full_path) < 0) - strlcpy(full_path, progname, sizeof(full_path)); - - if (ret == -1) - write_stderr(_("The program \"postgres\" is needed by %s " - "but was not found in the\n" - "same directory as \"%s\".\n" - "Check your installation.\n"), - progname, full_path); - else - write_stderr(_("The program \"postgres\" was found by \"%s\"\n" - "but was not the same version as %s.\n" - "Check your installation.\n"), - full_path, progname); - exit(1); - } - postgres_path = postmaster_path; - } + if (exec_path == NULL) + exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR); #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE) if (allow_core_files) @@ -1536,6 +1567,7 @@ do_help(void) printf(_("%s is a utility to start, stop, restart, reload configuration files,\n" "report the status of a PostgreSQL server, or signal a PostgreSQL process.\n\n"), progname); printf(_("Usage:\n")); + printf(_(" %s init[db] [-D DATADIR] [-s] [-o \"OPTIONS\"]\n"), progname); printf(_(" %s start [-w] [-t SECS] [-D DATADIR] [-s] [-l FILENAME] [-o \"OPTIONS\"]\n"), progname); printf(_(" %s stop [-W] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"), progname); printf(_(" %s restart [-w] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n" @@ -1568,7 +1600,7 @@ do_help(void) #endif printf(_(" -l, --log FILENAME write (or append) server log to FILENAME\n")); printf(_(" -o OPTIONS command line options to pass to postgres\n" - " (PostgreSQL server executable)\n")); + " (PostgreSQL server executable) or initdb\n")); printf(_(" -p PATH-TO-POSTGRES normally not necessary\n")); printf(_("\nOptions for stop or restart:\n")); printf(_(" -m SHUTDOWN-MODE can be \"smart\", \"fast\", or \"immediate\"\n")); @@ -1770,7 +1802,7 @@ main(int argc, char **argv) post_opts = xstrdup(optarg); break; case 'p': - postgres_path = xstrdup(optarg); + exec_path = xstrdup(optarg); break; case 'P': register_password = xstrdup(optarg); @@ -1825,7 +1857,10 @@ main(int argc, char **argv) exit(1); } - if (strcmp(argv[optind], "start") == 0) + if (strcmp(argv[optind], "init") == 0 + || strcmp(argv[optind], "initdb") == 0) + ctl_command = INIT_COMMAND; + else if (strcmp(argv[optind], "start") == 0) ctl_command = START_COMMAND; else if (strcmp(argv[optind], "stop") == 0) ctl_command = STOP_COMMAND; @@ -1922,6 +1957,9 @@ main(int argc, char **argv) switch (ctl_command) { + case INIT_COMMAND: + do_init(); + break; case STATUS_COMMAND: do_status(); break; -- 2.30.2