diff --git a/doc/src/sgml/ref/pg_ctl-ref.sgml b/doc/src/sgml/ref/pg_ctl-ref.sgml
index 45b53ce1a1a..52bcf5e8153 100644
--- a/doc/src/sgml/ref/pg_ctl-ref.sgml
+++ b/doc/src/sgml/ref/pg_ctl-ref.sgml
@@ -208,7 +208,8 @@ PostgreSQL documentation
the specified data directory. If it is, the PID
and the command line options that were used to invoke it are
displayed. If the server is not running, the process returns an
- exit status of 3.
+ exit status of 3. If an accessible data directory is not specified,
+ the process returns an exit status of 4.
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 0dbaa6e27fe..56d238f3948 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -97,6 +97,7 @@ static bool allow_core_files = false;
static time_t start_time;
static char postopts_file[MAXPGPATH];
+static char version_file[MAXPGPATH];
static char pid_file[MAXPGPATH];
static char backup_file[MAXPGPATH];
static char recovery_file[MAXPGPATH];
@@ -152,7 +153,7 @@ static void pgwin32_doRunAsService(void);
static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_service);
#endif
-static pgpid_t get_pgpid(void);
+static pgpid_t get_pgpid(bool is_status_request);
static char **readfile(const char *path);
static void free_readfile(char **optlines);
static int start_postmaster(void);
@@ -246,10 +247,34 @@ print_msg(const char *msg)
}
static pgpid_t
-get_pgpid(void)
+get_pgpid(bool is_status_request)
{
FILE *pidf;
long pid;
+ struct stat statbuf;
+
+ if (stat(pg_data, &statbuf) != 0)
+ {
+ if (errno == ENOENT)
+ printf(_("%s: directory \"%s\" does not exist\n"), progname,
+ pg_data);
+ else
+ printf(_("%s: cannot access directory \"%s\"\n"), progname,
+ pg_data);
+ /*
+ * The Linux Standard Base Core Specification 3.1 says this should return
+ * '4, program or service status is unknown'
+ * https://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
+ */
+ exit(is_status_request ? 4 : 1);
+ }
+
+ if (stat(version_file, &statbuf) != 0 && errno == ENOENT)
+ {
+ printf(_("%s: directory \"%s\" is not a database cluster directory\n"),
+ progname, pg_data);
+ exit(is_status_request ? 4 : 1);
+ }
pidf = fopen(pid_file, "r");
if (pidf == NULL)
@@ -810,7 +835,7 @@ do_start(void)
if (ctl_command != RESTART_COMMAND)
{
- old_pid = get_pgpid();
+ old_pid = get_pgpid(false);
if (old_pid != 0)
write_stderr(_("%s: another server might be running; "
"trying to start server anyway\n"),
@@ -894,7 +919,7 @@ do_stop(void)
pgpid_t pid;
struct stat statbuf;
- pid = get_pgpid();
+ pid = get_pgpid(false);
if (pid == 0) /* no pid file */
{
@@ -943,7 +968,7 @@ do_stop(void)
for (cnt = 0; cnt < wait_seconds; cnt++)
{
- if ((pid = get_pgpid()) != 0)
+ if ((pid = get_pgpid(false)) != 0)
{
print_msg(".");
pg_usleep(1000000); /* 1 sec */
@@ -980,7 +1005,7 @@ do_restart(void)
pgpid_t pid;
struct stat statbuf;
- pid = get_pgpid();
+ pid = get_pgpid(false);
if (pid == 0) /* no pid file */
{
@@ -1033,7 +1058,7 @@ do_restart(void)
for (cnt = 0; cnt < wait_seconds; cnt++)
{
- if ((pid = get_pgpid()) != 0)
+ if ((pid = get_pgpid(false)) != 0)
{
print_msg(".");
pg_usleep(1000000); /* 1 sec */
@@ -1071,7 +1096,7 @@ do_reload(void)
{
pgpid_t pid;
- pid = get_pgpid();
+ pid = get_pgpid(false);
if (pid == 0) /* no pid file */
{
write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
@@ -1110,7 +1135,7 @@ do_promote(void)
pgpid_t pid;
struct stat statbuf;
- pid = get_pgpid();
+ pid = get_pgpid(false);
if (pid == 0) /* no pid file */
{
@@ -1204,7 +1229,7 @@ do_status(void)
{
pgpid_t pid;
- pid = get_pgpid();
+ pid = get_pgpid(true);
/* Is there a pid file? */
if (pid != 0)
{
@@ -1247,7 +1272,7 @@ do_status(void)
/*
* The Linux Standard Base Core Specification 3.1 says this should return
- * '3'
+ * '3, program is not running'
* https://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
*/
exit(3);
@@ -2285,6 +2310,7 @@ main(int argc, char **argv)
if (pg_data)
{
snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
+ snprintf(version_file, MAXPGPATH, "%s/PG_VERSION", pg_data);
snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
snprintf(recovery_file, MAXPGPATH, "%s/recovery.conf", pg_data);