On Mon, 2013-01-14 at 06:37 -0500, Peter Eisentraut wrote:
> Here is a patch to add an option -I/--idempotent to pg_ctl, the result
> of which is that pg_ctl doesn't error on start or stop if the server is
> already running or already stopped.

So apparently, pg_upgrade needs the existing behavior, so making the
idempotent option the only behavior won't work.  Therefore, I think this
patch is still useful as originally presented.  I've made one change
that pg_ctl won't print any messages if the -I option is used and the
server is already started/stopped.
diff --git a/contrib/start-scripts/linux b/contrib/start-scripts/linux
index b950cf5..03c6e50 100644
--- a/contrib/start-scripts/linux
+++ b/contrib/start-scripts/linux
@@ -84,17 +84,17 @@ case $1 in
 	echo -n "Starting PostgreSQL: "
 	test x"$OOM_SCORE_ADJ" != x && echo "$OOM_SCORE_ADJ" > /proc/self/oom_score_adj
 	test x"$OOM_ADJ" != x && echo "$OOM_ADJ" > /proc/self/oom_adj
-	su - $PGUSER -c "$DAEMON -D '$PGDATA' &" >>$PGLOG 2>&1
+	su - $PGUSER -c "$DAEMON -I -D '$PGDATA' &" >>$PGLOG 2>&1
 	echo "ok"
 	;;
   stop)
 	echo -n "Stopping PostgreSQL: "
-	su - $PGUSER -c "$PGCTL stop -D '$PGDATA' -s -m fast"
+	su - $PGUSER -c "$PGCTL stop -I -D '$PGDATA' -s -m fast"
 	echo "ok"
 	;;
   restart)
 	echo -n "Restarting PostgreSQL: "
-	su - $PGUSER -c "$PGCTL stop -D '$PGDATA' -s -m fast -w"
+	su - $PGUSER -c "$PGCTL stop -I -D '$PGDATA' -s -m fast -w"
 	test x"$OOM_SCORE_ADJ" != x && echo "$OOM_SCORE_ADJ" > /proc/self/oom_score_adj
 	test x"$OOM_ADJ" != x && echo "$OOM_ADJ" > /proc/self/oom_adj
 	su - $PGUSER -c "$DAEMON -D '$PGDATA' &" >>$PGLOG 2>&1
diff --git a/doc/src/sgml/ref/pg_ctl-ref.sgml b/doc/src/sgml/ref/pg_ctl-ref.sgml
index 3107514..549730d 100644
--- a/doc/src/sgml/ref/pg_ctl-ref.sgml
+++ b/doc/src/sgml/ref/pg_ctl-ref.sgml
@@ -39,6 +39,7 @@
    <arg choice="opt"><option>-o</option> <replaceable>options</replaceable></arg>
    <arg choice="opt"><option>-p</option> <replaceable>path</replaceable></arg>
    <arg choice="opt"><option>-c</option></arg>
+   <arg choice="opt"><option>-I</option></arg>
   </cmdsynopsis>
 
   <cmdsynopsis>
@@ -55,6 +56,7 @@
        <arg choice="plain"><option>i[mmediate]</option></arg>
      </group>
    </arg>
+   <arg choice="opt"><option>-I</option></arg>
   </cmdsynopsis>
 
   <cmdsynopsis>
@@ -271,6 +273,25 @@ <title>Options</title>
      </varlistentry>
 
      <varlistentry>
+      <term><option>-I</option></term>
+      <term><option>--idempotent</option></term>
+      <listitem>
+       <para>
+        When used with the <literal>start</literal> or <literal>stop</literal>
+        actions, return exit code 0 if the server is already running or
+        stopped, respectively.  Otherwise, an error is raised and a nonzero
+        exit code is returned in these cases.
+       </para>
+
+       <para>
+        This option is useful for System-V-style init scripts, which require
+        the <literal>start</literal> and <literal>stop</literal> actions to be
+        idempotent.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
       <term><option>-l <replaceable class="parameter">filename</replaceable></option></term>
       <term><option>--log <replaceable class="parameter">filename</replaceable></option></term>
       <listitem>
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 7d5e168..f6b92d1 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -86,6 +86,7 @@
 static char *pgdata_opt = NULL;
 static char *post_opts = NULL;
 static const char *progname;
+static bool idempotent = false;
 static char *log_file = NULL;
 static char *exec_path = NULL;
 static char *register_servicename = "PostgreSQL";		/* FIXME: + version ID? */
@@ -774,9 +775,15 @@
 	{
 		old_pid = get_pgpid();
 		if (old_pid != 0)
-			write_stderr(_("%s: another server might be running; "
-						   "trying to start server anyway\n"),
-						 progname);
+		{
+			if (idempotent)
+				exit(0);
+			else
+			{
+				write_stderr(_("%s: another server might be running\n"), progname);
+				exit(1);
+			}
+		}
 	}
 
 	read_post_opts();
@@ -860,6 +867,8 @@
 
 	if (pid == 0)				/* no pid file */
 	{
+		if (idempotent)
+			exit(0);
 		write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
 		write_stderr(_("Is server running?\n"));
 		exit(1);
@@ -1764,9 +1773,9 @@
 	printf(_("%s is a utility to initialize, start, stop, or control a PostgreSQL server.\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"
+	printf(_("  %s start   [-w] [-t SECS] [-D DATADIR] [-s] [-I] [-l FILENAME] [-o \"OPTIONS\"]\n"), progname);
+	printf(_("  %s stop    [-W] [-t SECS] [-D DATADIR] [-s] [-I] [-m SHUTDOWN-MODE]\n"), progname);
+	printf(_("  %s restart [-w] [-t SECS] [-D DATADIR] [-s]      [-m SHUTDOWN-MODE]\n"
 			 "                 [-o \"OPTIONS\"]\n"), progname);
 	printf(_("  %s reload  [-D DATADIR] [-s]\n"), progname);
 	printf(_("  %s status  [-D DATADIR]\n"), progname);
@@ -1799,6 +1808,8 @@
 	printf(_("  -o OPTIONS             command line options to pass to postgres\n"
 	 "                         (PostgreSQL server executable) or initdb\n"));
 	printf(_("  -p PATH-TO-POSTGRES    normally not necessary\n"));
+	printf(_("\nOptions for start or stop:\n"));
+	printf(_("  -I, --idempotent       don't error if server already running or stopped\n"));
 	printf(_("\nOptions for stop, restart, or promote:\n"));
 	printf(_("  -m, --mode=MODE        MODE can be \"smart\", \"fast\", or \"immediate\"\n"));
 
@@ -1981,6 +1992,7 @@
 		{"silent", no_argument, NULL, 's'},
 		{"timeout", required_argument, NULL, 't'},
 		{"core-files", no_argument, NULL, 'c'},
+		{"idempotent", no_argument, NULL, 'I'},
 		{NULL, 0, NULL, 0}
 	};
 
@@ -2046,7 +2058,7 @@
 	/* process command-line options */
 	while (optind < argc)
 	{
-		while ((c = getopt_long(argc, argv, "cD:l:m:N:o:p:P:sS:t:U:wW", long_options, &option_index)) != -1)
+		while ((c = getopt_long(argc, argv, "cD:Il:m:N:o:p:P:sS:t:U:wW", long_options, &option_index)) != -1)
 		{
 			switch (c)
 			{
@@ -2072,6 +2084,9 @@
 								 pgdata_D);
 						break;
 					}
+				case 'I':
+					idempotent = true;
+					break;
 				case 'l':
 					log_file = pg_strdup(optarg);
 					break;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to