diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 5b5fc97c72..0650cc10e8 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -560,6 +560,45 @@ int			postmaster_alive_fds[2] = {-1, -1};
 HANDLE		PostmasterHandle;
 #endif
 
+char   *norm_args = NULL;  /* normalized arguments */
+char   *norm_args_tail = NULL;
+int		norm_args_len = 0;
+
+static void
+add_norm_argument(int opt, char *value)
+{
+	int valuelen = 0;
+
+	if (norm_args_len == 0)
+	{
+		norm_args_len = 128;
+		norm_args = malloc(norm_args_len);
+		norm_args_tail = norm_args;
+	}
+
+	if (opt == 0)
+	{
+		*norm_args_tail++ = '\0';   /* terminator */
+		return;
+	}
+
+	if (value)
+		valuelen = strlen(value) + 3;  /* _\"val\"*/
+
+	/* expand buffer as needed */
+	while (norm_args_tail - norm_args + 4 /* \"-x\" */ + valuelen + 1
+		   > norm_args_len)
+		norm_args_len *= 2;
+	norm_args = realloc(norm_args, norm_args_len);
+
+	*norm_args_tail++ = '\1';		/* delimiter */
+
+	if (value != NULL)
+		norm_args_tail += sprintf(norm_args_tail, "\"-%c\" \"%s\"", opt, value);
+	else
+		norm_args_tail += sprintf(norm_args_tail, "\"-%c\"", opt);
+}
+
 /*
  * Postmaster main entry point
  */
@@ -680,6 +719,8 @@ PostmasterMain(int argc, char *argv[])
 	 */
 	while ((opt = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:-:")) != -1)
 	{
+		add_norm_argument(opt, optarg);
+
 		switch (opt)
 		{
 			case 'B':
@@ -850,6 +891,9 @@ PostmasterMain(int argc, char *argv[])
 		}
 	}
 
+	/* terminate normalized arguemnt list */
+	add_norm_argument(0, NULL);
+
 	/*
 	 * Postmaster accepts no non-option switch arguments.
 	 */
@@ -5666,7 +5710,6 @@ static bool
 CreateOptsFile(int argc, char *argv[], char *fullprogname)
 {
 	FILE	   *fp;
-	int			i;
 
 #define OPTS_FILE	"postmaster.opts"
 
@@ -5677,8 +5720,8 @@ CreateOptsFile(int argc, char *argv[], char *fullprogname)
 	}
 
 	fprintf(fp, "%s", fullprogname);
-	for (i = 1; i < argc; i++)
-		fprintf(fp, " \"%s\"", argv[i]);
+	if (norm_args)
+		fprintf(fp, "%s", norm_args);
 	fputs("\n", fp);
 
 	if (fclose(fp))
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 1cdc3ebaa3..b4ccaf224f 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -755,10 +755,37 @@ read_post_opts(void)
 				 * Are we at the first option, as defined by space and
 				 * double-quote?
 				 */
-				if ((arg1 = strstr(optline, " \"")) != NULL)
+				if ((arg1 = strstr(optline, "\1\"")) != NULL)
 				{
+					char *pto;
+					char *pfrom;
+
 					*arg1 = '\0';	/* terminate so we get only program name */
 					post_opts = pg_strdup(arg1 + 1);	/* point past whitespace */
+
+					pto = pfrom = post_opts;
+					while (*pfrom)
+					{
+						if (*pfrom != '\1')
+						{
+							*pto++ = *pfrom++;
+							continue;
+						}
+
+						pfrom++;
+
+						/* Remove -D optsion if we have a replacment */
+						if (pgdata_opt && strncmp(pfrom, "\"-D\"", 4) == 0)
+						{
+							/* Skip -D option */
+							while (*pfrom && *pfrom != '\1') pfrom++;
+							continue;
+						}
+
+						/* replace '\1' with a space */
+						*pto++ = ' ';
+					}
+					*pto = 0;
 				}
 				if (exec_path == NULL)
 					exec_path = pg_strdup(optline);
@@ -870,8 +897,8 @@ do_start(void)
 
 	read_post_opts();
 
-	/* No -D or -D already added during server start */
-	if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
+	/* Use "" for printf safety */
+	if (pgdata_opt == NULL)
 		pgdata_opt = "";
 
 	if (exec_path == NULL)
