diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index 0fec73ec7dc82f395afe32d29b88e3f6c83c8fbf..efb080befd4355e68981b35dc32e9b954e10810b 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -184,8 +184,8 @@ issue_warnings(char *sequence_script_file_name)
 		{
 			prep_status("Adjusting sequences");
 			exec_prog(UTILITY_LOG_FILE, NULL, true,
-					  "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
-					  new_cluster.bindir, new_cluster.port, os_info.user,
+					  "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
+					  new_cluster.bindir, cluster_conn_opts(&new_cluster),
 					  sequence_script_file_name);
 			unlink(sequence_script_file_name);
 			check_ok();
diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c
index cfc4017d517a3ca093fef101df83c4b9914bbf14..b905ab084d7337dc4fc5c5b064e09c9c3ab00552 100644
--- a/contrib/pg_upgrade/dump.c
+++ b/contrib/pg_upgrade/dump.c
@@ -24,8 +24,8 @@ generate_old_dump(void)
 	 * restores the frozenid's for databases and relations.
 	 */
 	exec_prog(UTILITY_LOG_FILE, NULL, true,
-			  "\"%s/pg_dumpall\" --port %d --username \"%s\" --schema-only --binary-upgrade %s -f %s",
-			  new_cluster.bindir, old_cluster.port, os_info.user,
+			  "\"%s/pg_dumpall\" %s --schema-only --binary-upgrade %s -f %s",
+			  new_cluster.bindir, cluster_conn_opts(&old_cluster),
 			  log_opts.verbose ? "--verbose" : "",
 			  ALL_DUMP_FILE);
 	check_ok();
diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c
index 94bce505cb6bda2473442ea1231bb439411ddabc..6d5a93a0a566d433222d97ab762a91bc39274a3f 100644
--- a/contrib/pg_upgrade/option.c
+++ b/contrib/pg_upgrade/option.c
@@ -9,6 +9,8 @@
 
 #include "postgres.h"
 
+#include "miscadmin.h"
+
 #include "pg_upgrade.h"
 
 #include <getopt_long.h>
@@ -376,3 +378,64 @@ adjust_data_dir(ClusterInfo *cluster)
 
 	check_ok();
 }
+
+
+/*
+ * get_sock_dir
+ *
+ * Identify the socket directory to use for this cluster.  If we're doing
+ * a live check (old cluster only), we need to find out where the postmaster
+ * is listening.  Otherwise, we're going to put the socket into the current
+ * directory.
+ */
+void
+get_sock_dir(ClusterInfo *cluster, bool live_check)
+{
+#ifdef HAVE_UNIX_SOCKETS
+	if (!live_check)
+	{
+		/* Use the current directory for the socket */
+		cluster->sockdir = pg_malloc(MAXPGPATH);
+		if (!getcwd(cluster->sockdir, MAXPGPATH))
+			pg_log(PG_FATAL, "cannot find current directory\n");
+	}
+	else
+	{
+		/*
+		 *	If we are doing a live check, we will use the old cluster's Unix
+		 *	domain socket directory so we can connect to the live server.
+		 */
+
+		/* sockdir was added to postmaster.pid in PG 9.1 */
+		if (GET_MAJOR_VERSION(cluster->major_version) >= 901)
+		{
+			char		filename[MAXPGPATH];
+			FILE		*fp;
+			int			i;
+
+			snprintf(filename, sizeof(filename), "%s/postmaster.pid",
+					 cluster->pgdata);
+			if ((fp = fopen(filename, "r")) == NULL)
+				pg_log(PG_FATAL, "Could not get socket directory of the old server\n");
+
+			cluster->sockdir = pg_malloc(MAXPGPATH);
+			for (i = 0; i < LOCK_FILE_LINE_SOCKET_DIR; i++)
+				if (fgets(cluster->sockdir, MAXPGPATH, fp) == NULL)
+					pg_log(PG_FATAL, "Could not get socket directory of the old server\n");
+
+			fclose(fp);
+
+			/* Remove trailing newline */
+			if (strchr(cluster->sockdir, '\n') != NULL)
+				*strchr(cluster->sockdir, '\n') = '\0';
+		}
+		else
+		{
+			/* Can't get live sockdir, so assume the default is OK. */
+			cluster->sockdir = NULL;
+		}
+	}
+#else /* !HAVE_UNIX_SOCKETS */
+	cluster->sockdir = NULL;
+#endif
+}
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
index c47c8bba4452da03fd2174682f0679ada45aa38c..ee3a1517f49042b31571e0d0ba3ad34975a2d2ee 100644
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ b/contrib/pg_upgrade/pg_upgrade.c
@@ -88,6 +88,9 @@ main(int argc, char **argv)
 	check_cluster_versions();
 	check_cluster_compatibility(live_check);
 
+	get_sock_dir(&old_cluster, live_check);
+	get_sock_dir(&new_cluster, false);
+
 	check_old_cluster(live_check, &sequence_script_file_name);
 
 
@@ -211,8 +214,8 @@ prepare_new_cluster(void)
 	 */
 	prep_status("Analyzing all rows in the new cluster");
 	exec_prog(UTILITY_LOG_FILE, NULL, true,
-			  "\"%s/vacuumdb\" --port %d --username \"%s\" --all --analyze %s",
-			  new_cluster.bindir, new_cluster.port, os_info.user,
+			  "\"%s/vacuumdb\" %s --all --analyze %s",
+			  new_cluster.bindir, cluster_conn_opts(&new_cluster),
 			  log_opts.verbose ? "--verbose" : "");
 	check_ok();
 
@@ -224,8 +227,8 @@ prepare_new_cluster(void)
 	 */
 	prep_status("Freezing all rows on the new cluster");
 	exec_prog(UTILITY_LOG_FILE, NULL, true,
-			  "\"%s/vacuumdb\" --port %d --username \"%s\" --all --freeze %s",
-			  new_cluster.bindir, new_cluster.port, os_info.user,
+			  "\"%s/vacuumdb\" %s --all --freeze %s",
+			  new_cluster.bindir, cluster_conn_opts(&new_cluster),
 			  log_opts.verbose ? "--verbose" : "");
 	check_ok();
 
@@ -261,8 +264,8 @@ prepare_new_databases(void)
 	 * the template0 template.
 	 */
 	exec_prog(RESTORE_LOG_FILE, NULL, true,
-			  "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
-			  new_cluster.bindir, new_cluster.port, os_info.user,
+			  "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
+			  new_cluster.bindir, cluster_conn_opts(&new_cluster),
 			  GLOBALS_DUMP_FILE);
 	check_ok();
 
@@ -290,8 +293,8 @@ create_new_objects(void)
 
 	prep_status("Restoring database schema to new cluster");
 	exec_prog(RESTORE_LOG_FILE, NULL, true,
-			  "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
-			  new_cluster.bindir, new_cluster.port, os_info.user,
+			  "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
+			  new_cluster.bindir, cluster_conn_opts(&new_cluster),
 			  DB_DUMP_FILE);
 	check_ok();
 
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
index fa4c6c0a478484da1a99f059cab33ff17502903e..7b19d916fff7201e0be1f60de865329c2c98061e 100644
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ b/contrib/pg_upgrade/pg_upgrade.h
@@ -226,6 +226,7 @@ typedef struct
 	char	   *bindir;			/* pathname for cluster's executable directory */
 	char	   *pgopts;			/* options to pass to the server, like pg_ctl
 								 * -o */
+	char	   *sockdir;		/* directory for Unix Domain socket, if any */
 	unsigned short port;		/* port number where postmaster is waiting */
 	uint32		major_version;	/* PG_VERSION of cluster */
 	char		major_version_str[64];	/* string PG_VERSION of cluster */
@@ -387,6 +388,7 @@ void print_maps(FileNameMap *maps, int n,
 
 void		parseCommandLine(int argc, char *argv[]);
 void		adjust_data_dir(ClusterInfo *cluster);
+void		get_sock_dir(ClusterInfo *cluster, bool live_check);
 
 /* relfilenode.c */
 
@@ -407,6 +409,8 @@ PGresult *
 executeQueryOrDie(PGconn *conn, const char *fmt,...)
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
 
+char	   *cluster_conn_opts(ClusterInfo *cluster);
+
 void		start_postmaster(ClusterInfo *cluster);
 void		stop_postmaster(bool fast);
 uint32		get_major_server_version(ClusterInfo *cluster);
diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
index 1fb0d6ccceb2d6efd750d00402778cd0314936b1..11e7e75d78f8947478be0b092cf135a2a7783614 100644
--- a/contrib/pg_upgrade/server.c
+++ b/contrib/pg_upgrade/server.c
@@ -46,21 +46,54 @@ connectToServer(ClusterInfo *cluster, const char *db_name)
 /*
  * get_db_conn()
  *
- * get database connection
+ * get database connection, using named database + standard params for cluster
  */
 static PGconn *
 get_db_conn(ClusterInfo *cluster, const char *db_name)
 {
-	char		conn_opts[MAXPGPATH];
+	char		conn_opts[2 * NAMEDATALEN + MAXPGPATH + 100];
 
-	snprintf(conn_opts, sizeof(conn_opts),
-			 "dbname = '%s' user = '%s' port = %d", db_name, os_info.user,
-			 cluster->port);
+	if (cluster->sockdir)
+		snprintf(conn_opts, sizeof(conn_opts),
+				 "dbname = '%s' user = '%s' host = '%s' port = %d",
+				 db_name, os_info.user, cluster->sockdir, cluster->port);
+	else
+		snprintf(conn_opts, sizeof(conn_opts),
+				 "dbname = '%s' user = '%s' port = %d",
+				 db_name, os_info.user, cluster->port);
 
 	return PQconnectdb(conn_opts);
 }
 
 
+/*
+ * cluster_conn_opts()
+ *
+ * Return standard command-line options for connecting to this cluster when
+ * using psql, pg_dump, etc.  Ideally this would match what get_db_conn()
+ * sets, but the utilities we need aren't very consistent about the treatment
+ * of database name options, so we leave that out.
+ *
+ * Note result is in static storage, so use it right away.
+ */
+char *
+cluster_conn_opts(ClusterInfo *cluster)
+{
+	static char	conn_opts[MAXPGPATH + NAMEDATALEN + 100];
+
+	if (cluster->sockdir)
+		snprintf(conn_opts, sizeof(conn_opts),
+				 "--host \"%s\" --port %d --username \"%s\"",
+				 cluster->sockdir, cluster->port, os_info.user);
+	else
+		snprintf(conn_opts, sizeof(conn_opts),
+				 "--port %d --username \"%s\"",
+				 cluster->port, os_info.user);
+
+	return conn_opts;
+}
+
+
 /*
  * executeQueryOrDie()
  *
@@ -140,10 +173,11 @@ stop_postmaster_atexit(void)
 void
 start_postmaster(ClusterInfo *cluster)
 {
-	char		cmd[MAXPGPATH];
+	char		cmd[MAXPGPATH * 4 + 1000];
 	PGconn	   *conn;
 	bool		exit_hook_registered = false;
 	bool		pg_ctl_return = false;
+	char		socket_string[MAXPGPATH + 200];
 
 	if (!exit_hook_registered)
 	{
@@ -151,6 +185,23 @@ start_postmaster(ClusterInfo *cluster)
 		exit_hook_registered = true;
 	}
 
+	socket_string[0] = '\0';
+
+#ifdef HAVE_UNIX_SOCKETS
+	/* prevent TCP/IP connections, restrict socket access */
+	strcat(socket_string,
+		   " -c listen_addresses='' -c unix_socket_permissions=0700");
+
+	/* Have a sockdir?  Tell the postmaster. */
+	if (cluster->sockdir)
+		snprintf(socket_string + strlen(socket_string),
+				 sizeof(socket_string) - strlen(socket_string),
+				 " -c %s='%s'",
+				 (GET_MAJOR_VERSION(cluster->major_version) < 903) ?
+				 "unix_socket_directory" : "unix_socket_directories",
+				 cluster->sockdir);
+#endif
+
 	/*
 	 * Using autovacuum=off disables cleanup vacuum and analyze, but freeze
 	 * vacuums can still happen, so we set autovacuum_freeze_max_age to its
@@ -159,12 +210,12 @@ start_postmaster(ClusterInfo *cluster)
 	 * not touch them.
 	 */
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d %s %s\" start",
+			 "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d %s %s%s\" start",
 		  cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
 			 (cluster->controldata.cat_ver >=
 			  BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
 			 "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
-			 cluster->pgopts ? cluster->pgopts : "");
+			 cluster->pgopts ? cluster->pgopts : "", socket_string);
 
 	/*
 	 * Don't throw an error right away, let connecting throw the error because
diff --git a/doc/src/sgml/pgupgrade.sgml b/doc/src/sgml/pgupgrade.sgml
index b62aba26418d9cd3f5918455727e046fca0d4d42..9e43f3ce133ef6b29de12694bfa92bce3a1d0dac 100644
--- a/doc/src/sgml/pgupgrade.sgml
+++ b/doc/src/sgml/pgupgrade.sgml
@@ -519,6 +519,14 @@ psql --username postgres --file script.sql postgres
    <literal>-d /real-data-directory -o '-D /configuration-directory'</>.
   </para>
 
+  <para>
+   If doing <option>--check</> with a running old server of a pre-9.1 version,
+   and the old server is using a Unix-domain socket directory that is
+   different from the default built into the new <productname>PostgreSQL</>
+   installation, set <envar>PGHOST</> to point to the socket location of the
+   old server.  (This is not relevant on Windows.)
+  </para>
+
   <para>
    A Log-Shipping Standby Server (<xref linkend="warm-standby">) cannot
    be upgraded because the server must allow writes.  The simplest way