diff -durpN postgresql.orig/doc/src/sgml/ref/pg_basebackup.sgml postgresql/doc/src/sgml/ref/pg_basebackup.sgml --- postgresql.orig/doc/src/sgml/ref/pg_basebackup.sgml 2012-06-18 07:06:42.774009894 +0200 +++ postgresql/doc/src/sgml/ref/pg_basebackup.sgml 2012-07-01 12:51:51.050652170 +0200 @@ -186,6 +186,28 @@ PostgreSQL documentation + + + + + Write a minimal recovery.conf into the output directory using + the connection parameters from the command line to ease + setting up the standby. Conflicts with + + + + + + + + + + Start the standby database server. Implies . + + + + + diff -durpN postgresql.orig/src/bin/pg_basebackup/pg_basebackup.c postgresql/src/bin/pg_basebackup/pg_basebackup.c --- postgresql.orig/src/bin/pg_basebackup/pg_basebackup.c 2012-06-26 09:10:21.301759598 +0200 +++ postgresql/src/bin/pg_basebackup/pg_basebackup.c 2012-07-01 12:44:36.920813960 +0200 @@ -46,6 +46,8 @@ int compresslevel = 0; bool includewal = false; bool streamwal = false; bool fastcheckpoint = false; +bool writerecoveryconf = false; +bool startstandby = false; int standby_message_timeout = 10 * 1000; /* 10 sec = default */ /* Progress counters */ @@ -107,6 +109,10 @@ usage(void) printf(_("\nOptions controlling the output:\n")); printf(_(" -D, --pgdata=DIRECTORY receive base backup into directory\n")); printf(_(" -F, --format=p|t output format (plain (default), tar)\n")); + printf(_(" -R, --write-recovery-conf\n" + " write recovery.conf after backup\n")); + printf(_(" -S, --start-standby start standby after backup, implies -R\n" + " conflicts with -x\n")); printf(_(" -x, --xlog include required WAL files in backup (fetch mode)\n")); printf(_(" -X, --xlog-method=fetch|stream\n" " include required WAL files with specified method\n")); @@ -1193,6 +1199,85 @@ BaseBackup(void) fprintf(stderr, "%s: base backup completed\n", progname); } +static void WriteRecoveryConf(void) +{ + char filename[MAXPGPATH]; + char cfhost[MAXPGPATH] = ""; + char cfport[MAXPGPATH] = ""; + char cfuser[MAXPGPATH] = ""; + char cfpass[MAXPGPATH] = ""; + FILE *cf; + + if (!writerecoveryconf) + return; + + memset(cfhost, 0, MAXPGPATH); + if (dbhost) + snprintf(cfhost, MAXPGPATH-1, "host=%s", dbhost); + + memset(cfport, 0, MAXPGPATH); + if (dbport) + snprintf(cfport, MAXPGPATH-1, "port=%s", dbport); + + memset(cfuser, 0, MAXPGPATH); + if (dbuser) + snprintf(cfuser, MAXPGPATH-1, "user=%s", dbuser); + + memset(cfpass, 0, MAXPGPATH); + if (dbpassword) + snprintf(cfpass, MAXPGPATH-1, "password='%s'", dbpassword); + else + printf("add password to primary_conninfo in %s if needed\n", filename); + + sprintf(filename, "%s/recovery.conf", basedir); + + cf = fopen(filename, "w"); + if (cf == NULL) + { + fprintf(stderr, _("cannot create %s"), filename); + exit(1); + } + + fprintf(cf, "standby_mode = 'on'\n"); + fprintf(cf, "primary_conninfo = '%s %s %s'\n", cfhost, cfport, cfuser); + + fclose(cf); +} + +static void StartStandby(const char *command) +{ + char *path; + char *args[5]; + int pos, len; + + if (!startstandby) + return; + + path = xstrdup(command); + len = strlen(path); + + for (pos = len; pos > 0; pos--) + { + if (path[pos - 1] == '/' +#ifdef WIN32 + || path[pos - 1] == '\\' +#endif + ) + break; + } + + sprintf(&path[pos], "pg_ctl"); + + args[0] = path; + args[1] = "-D"; + args[2] = basedir; + args[3] = "start"; + args[4] = NULL; + + if (execvp(path, args) < 0) + fprintf(stderr, _("Cannot execute pg_ctl: %s"), + strerror(errno)); +} int main(int argc, char **argv) @@ -1203,6 +1288,8 @@ main(int argc, char **argv) {"pgdata", required_argument, NULL, 'D'}, {"format", required_argument, NULL, 'F'}, {"checkpoint", required_argument, NULL, 'c'}, + {"write-recovery-conf", no_argument, NULL, 'R'}, + {"start-standby", no_argument, NULL, 'S'}, {"xlog", no_argument, NULL, 'x'}, {"xlog-method", required_argument, NULL, 'X'}, {"gzip", no_argument, NULL, 'z'}, @@ -1240,7 +1327,7 @@ main(int argc, char **argv) } } - while ((c = getopt_long(argc, argv, "D:F:xX:l:zZ:c:h:p:U:s:wWvP", + while ((c = getopt_long(argc, argv, "D:F:RSxX:l:zZ:c:h:p:U:s:wWvP", long_options, &option_index)) != -1) { switch (c) @@ -1260,6 +1347,12 @@ main(int argc, char **argv) exit(1); } break; + case 'R': + writerecoveryconf = true; + break; + case 'S': + startstandby = true; + break; case 'x': if (includewal) { @@ -1422,6 +1515,16 @@ main(int argc, char **argv) } #endif + if (startstandby) + writerecoveryconf = true; + + if (writerecoveryconf && includewal) + { + fprintf(stderr, + _("--xlog and --writerecoveryconf are mutually exclusive\n")); + exit(1); + } + /* * Verify that the target directory exists, or create it. For plaintext * backups, always require the directory. For tar backups, require it @@ -1433,5 +1536,9 @@ main(int argc, char **argv) BaseBackup(); + WriteRecoveryConf(); + + StartStandby(argv[0]); + return 0; } diff -durpN postgresql.orig/src/bin/pg_basebackup/streamutil.c postgresql/src/bin/pg_basebackup/streamutil.c --- postgresql.orig/src/bin/pg_basebackup/streamutil.c 2012-06-11 06:22:48.200921787 +0200 +++ postgresql/src/bin/pg_basebackup/streamutil.c 2012-07-01 12:09:56.938418170 +0200 @@ -28,7 +28,7 @@ char *dbhost = NULL; char *dbuser = NULL; char *dbport = NULL; int dbgetpassword = 0; /* 0=auto, -1=never, 1=always */ -static char *dbpassword = NULL; +char *dbpassword = NULL; PGconn *conn = NULL; /* diff -durpN postgresql.orig/src/bin/pg_basebackup/streamutil.h postgresql/src/bin/pg_basebackup/streamutil.h --- postgresql.orig/src/bin/pg_basebackup/streamutil.h 2012-04-16 19:57:22.589917242 +0200 +++ postgresql/src/bin/pg_basebackup/streamutil.h 2012-07-01 12:09:42.562326418 +0200 @@ -5,6 +5,7 @@ extern char *dbhost; extern char *dbuser; extern char *dbport; extern int dbgetpassword; +extern char *dbpassword; /* Connection kept global so we can disconnect easily */ extern PGconn *conn;