Skip to content
Snippets Groups Projects
Commit ac2e9673 authored by Robert Haas's avatar Robert Haas
Browse files

pg_isready

New command-line utility to test whether a server is ready to
accept connections.

Phil Sorber, reviewed by Michael Paquier and Peter Eisentraut
parent 0ac5ad51
No related branches found
No related tags found
No related merge requests found
...@@ -175,6 +175,7 @@ Complete list of usable sgml source files in this directory. ...@@ -175,6 +175,7 @@ Complete list of usable sgml source files in this directory.
<!ENTITY pgCtl SYSTEM "pg_ctl-ref.sgml"> <!ENTITY pgCtl SYSTEM "pg_ctl-ref.sgml">
<!ENTITY pgDump SYSTEM "pg_dump.sgml"> <!ENTITY pgDump SYSTEM "pg_dump.sgml">
<!ENTITY pgDumpall SYSTEM "pg_dumpall.sgml"> <!ENTITY pgDumpall SYSTEM "pg_dumpall.sgml">
<!ENTITY pgIsready SYSTEM "pg_isready.sgml">
<!ENTITY pgReceivexlog SYSTEM "pg_receivexlog.sgml"> <!ENTITY pgReceivexlog SYSTEM "pg_receivexlog.sgml">
<!ENTITY pgResetxlog SYSTEM "pg_resetxlog.sgml"> <!ENTITY pgResetxlog SYSTEM "pg_resetxlog.sgml">
<!ENTITY pgRestore SYSTEM "pg_restore.sgml"> <!ENTITY pgRestore SYSTEM "pg_restore.sgml">
......
<!--
doc/src/sgml/ref/pg_isready.sgml
PostgreSQL documentation
-->
<refentry id="app-pg-isready">
<refmeta>
<refentrytitle><application>pg_isready</application></refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo>Application</refmiscinfo>
</refmeta>
<refnamediv>
<refname>pg_isready</refname>
<refpurpose>checks the connection status of a <productname>PostgreSQL</productname> server</refpurpose>
</refnamediv>
<indexterm zone="app-pg-isready">
<primary>pg_isready</primary>
</indexterm>
<refsynopsisdiv>
<cmdsynopsis>
<command>pg_isready</command>
<arg rep="repeat"><replaceable>connection-option</replaceable></arg>
<arg rep="repeat"><replaceable>option</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1 id="app-pg-isready-description">
<title>Description</title>
<para>
<application>pg_isready</application> is a utility for checking the connection
status of a <productname>PostgreSQL</productname> database server. The exit
status specifies the result of the connection check.
</para>
</refsect1>
<refsect1 id="app-pg-isready-options">
<title>Options</title>
<variablelist>
<varlistentry>
<term><option>-d <replaceable class="parameter">dbname</replaceable></></term>
<term><option>--dbname=<replaceable class="parameter">dbname</replaceable></></term>
<listitem>
<para>
Specifies the name of the database to connect to.
</para>
<para>
If this parameter contains an <symbol>=</symbol> sign or starts
with a valid <acronym>URI</acronym> prefix
(<literal>postgresql://</literal>
or <literal>postgres://</literal>), it is treated as a
<parameter>conninfo</parameter> string. See <xref linkend="libpq-connect"> for more information.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-h <replaceable class="parameter">hostname</replaceable></></term>
<term><option>--host=<replaceable class="parameter">hostname</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the
server is running. If the value begins
with a slash, it is used as the directory for the Unix-domain
socket.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
<term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or the local Unix-domain
socket file extension on which the server is listening for
connections. Defaults to the value of the <envar>PGPORT</envar>
environment variable or, if not set, to the port specified at
compile time, usually 5432.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-q</option></term>
<term><option>--quiet</option></term>
<listitem>
<para>
Do not display status message. This is useful when scripting.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
<term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
Connect to the database as the user <replaceable
class="parameter">username</replaceable> instead of the default.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-V</></term>
<term><option>--version</></term>
<listitem>
<para>
Print the <application>pg_isready</application> version and exit.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-?</></term>
<term><option>--help</></term>
<listitem>
<para>
Show help about <application>pg_isready</application> command line
arguments, and exit.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Exit Status</title>
<para>
<application>pg_isready</application> returns <literal>0</literal> to the shell if the server
is accepting connections normally, <literal>1</literal> if the server is rejecting
connections (for example during startup), <literal>2</literal> if there was no response to the
connection attempt, and <literal>3</literal> if no attempt was made (for example due to invalid
parameters).
</para>
</refsect1>
<refsect1>
<title>Environment</title>
<para>
<command>pg_isready</command>, like most other <productname>PostgreSQL</>
utilities,
also uses the environment variables supported by <application>libpq</>
(see <xref linkend="libpq-envars">).
</para>
</refsect1>
<refsect1 id="app-pg-isready-notes">
<title>Notes</title>
<para>
The options <option>--dbname</> and <option>--username</> can be used to avoid gratuitous
error messages in the logs, but are not necessary for proper functionality.
</para>
</refsect1>
<refsect1 id="app-pg-isready-examples">
<title>Examples</title>
<para>
Standard Usage:
<screen>
<prompt>$</prompt> <userinput>pg_isready</userinput>
<computeroutput>/tmp:5432 - accepting connections</computeroutput>
<prompt>$</prompt> <userinput>echo $?</userinput>
<computeroutput>0</computeroutput>
</screen>
</para>
<para>
Running with connection parameters to a <productname>PostgreSQL</productname> cluster in startup:
<screen>
<prompt>$ </prompt><userinput>pg_isready -h localhost -p 5433</userinput>
<computeroutput>localhost:5433 - rejecting connections</computeroutput>
<prompt>$</prompt> <userinput>echo $?</userinput>
<computeroutput>1</computeroutput>
</screen>
</para>
<para>
Running with connection parameters to a non-responsive <productname>PostgreSQL</productname> cluster:
<screen>
<prompt>$ </prompt><userinput>pg_isready -h someremotehost</userinput>
<computeroutput>someremotehost:5432 - no response</computeroutput>
<prompt>$</prompt> <userinput>echo $?</userinput>
<computeroutput>2</computeroutput>
</screen>
</para>
</refsect1>
</refentry>
...@@ -223,6 +223,7 @@ ...@@ -223,6 +223,7 @@
&pgConfig; &pgConfig;
&pgDump; &pgDump;
&pgDumpall; &pgDumpall;
&pgIsready;
&pgReceivexlog; &pgReceivexlog;
&pgRestore; &pgRestore;
&psqlRef; &psqlRef;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
/dropuser /dropuser
/reindexdb /reindexdb
/vacuumdb /vacuumdb
/pg_isready
/dumputils.c /dumputils.c
/keywords.c /keywords.c
......
...@@ -16,7 +16,7 @@ subdir = src/bin/scripts ...@@ -16,7 +16,7 @@ subdir = src/bin/scripts
top_builddir = ../../.. top_builddir = ../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
PROGRAMS = createdb createlang createuser dropdb droplang dropuser clusterdb vacuumdb reindexdb PROGRAMS = createdb createlang createuser dropdb droplang dropuser clusterdb vacuumdb reindexdb pg_isready
override CPPFLAGS := -I$(top_srcdir)/src/bin/pg_dump -I$(top_srcdir)/src/bin/psql -I$(libpq_srcdir) $(CPPFLAGS) override CPPFLAGS := -I$(top_srcdir)/src/bin/pg_dump -I$(top_srcdir)/src/bin/psql -I$(libpq_srcdir) $(CPPFLAGS)
...@@ -34,6 +34,7 @@ dropuser: dropuser.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq ...@@ -34,6 +34,7 @@ dropuser: dropuser.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
clusterdb: clusterdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq clusterdb: clusterdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
vacuumdb: vacuumdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq vacuumdb: vacuumdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
reindexdb: reindexdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq reindexdb: reindexdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
pg_isready: pg_isready.o common.o | submake-libpq submake-libpgport
dumputils.c keywords.c: % : $(top_srcdir)/src/bin/pg_dump/% dumputils.c keywords.c: % : $(top_srcdir)/src/bin/pg_dump/%
rm -f $@ && $(LN_S) $< . rm -f $@ && $(LN_S) $< .
...@@ -54,6 +55,7 @@ install: all installdirs ...@@ -54,6 +55,7 @@ install: all installdirs
$(INSTALL_PROGRAM) clusterdb$(X) '$(DESTDIR)$(bindir)'/clusterdb$(X) $(INSTALL_PROGRAM) clusterdb$(X) '$(DESTDIR)$(bindir)'/clusterdb$(X)
$(INSTALL_PROGRAM) vacuumdb$(X) '$(DESTDIR)$(bindir)'/vacuumdb$(X) $(INSTALL_PROGRAM) vacuumdb$(X) '$(DESTDIR)$(bindir)'/vacuumdb$(X)
$(INSTALL_PROGRAM) reindexdb$(X) '$(DESTDIR)$(bindir)'/reindexdb$(X) $(INSTALL_PROGRAM) reindexdb$(X) '$(DESTDIR)$(bindir)'/reindexdb$(X)
$(INSTALL_PROGRAM) pg_isready$(X) '$(DESTDIR)$(bindir)'/pg_isready$(X)
installdirs: installdirs:
$(MKDIR_P) '$(DESTDIR)$(bindir)' $(MKDIR_P) '$(DESTDIR)$(bindir)'
......
/*-------------------------------------------------------------------------
*
* pg_isready --- checks the status of the PostgreSQL server
*
* Copyright (c) 2013, PostgreSQL Global Development Group
*
* src/bin/scripts/pg_isready.c
*
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include "common.h"
static void
help(const char *progname);
int
main(int argc, char **argv)
{
int c,optindex,opt_index = 0;
const char *progname;
const char *pghost = NULL;
const char *pgport = NULL;
const char *pguser = NULL;
const char *pgdbname = NULL;
const char *keywords[4], *values[4];
bool quiet = false;
PGPing rv;
PQconninfoOption *connect_options, *conn_opt_ptr;
/*
* We accept user and database as options to avoid
* useless errors from connecting with invalid params
*/
static struct option long_options[] = {
{"dbname", required_argument, NULL, 'd'},
{"host", required_argument, NULL, 'h'},
{"port", required_argument, NULL, 'p'},
{"quiet", no_argument, NULL, 'q'},
{"username", required_argument, NULL, 'U'},
{NULL, 0, NULL, 0}
};
progname = get_progname(argv[0]);
handle_help_version_opts(argc, argv, progname, help);
while ((c = getopt_long(argc, argv, "d:h:p:qU:V", long_options, &optindex)) != -1)
{
switch (c)
{
case 'd':
pgdbname = pg_strdup(optarg);
break;
case 'h':
pghost = pg_strdup(optarg);
break;
case 'p':
pgport = pg_strdup(optarg);
break;
case 'q':
quiet = true;
break;
case 'U':
pguser = pg_strdup(optarg);
break;
default:
/*
* We need to make sure we don't return 1 here because someone
* checking the return code might infer unintended meaning
*/
exit(PQPING_NO_ATTEMPT);
}
}
if (optind < argc)
{
fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
progname, argv[optind]);
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
/*
* We need to make sure we don't return 1 here because someone
* checking the return code might infer unintended meaning
*/
exit(PQPING_NO_ATTEMPT);
}
/*
* Get the default options so we can display them in our output
*/
connect_options = PQconndefaults();
conn_opt_ptr = connect_options;
while (conn_opt_ptr->keyword)
{
if (strncmp(conn_opt_ptr->keyword, "host", 5) == 0)
{
if (pghost)
{
keywords[opt_index] = conn_opt_ptr->keyword;
values[opt_index] = pghost;
opt_index++;
}
else if (conn_opt_ptr->val)
pghost = conn_opt_ptr->val;
else
pghost = DEFAULT_PGSOCKET_DIR;
}
else if (strncmp(conn_opt_ptr->keyword, "port", 5) == 0)
{
if (pgport)
{
keywords[opt_index] = conn_opt_ptr->keyword;
values[opt_index] = pgport;
opt_index++;
}
else if (conn_opt_ptr->val)
pgport = conn_opt_ptr->val;
}
else if (strncmp(conn_opt_ptr->keyword, "user", 5) == 0)
{
if (pguser)
{
keywords[opt_index] = conn_opt_ptr->keyword;
values[opt_index] = pguser;
opt_index++;
}
else if (conn_opt_ptr->val)
pguser = conn_opt_ptr->val;
}
else if (strncmp(conn_opt_ptr->keyword, "dbname", 7) == 0)
{
if (pgdbname)
{
keywords[opt_index] = conn_opt_ptr->keyword;
values[opt_index] = pgdbname;
opt_index++;
}
else if (conn_opt_ptr->val)
pgdbname = conn_opt_ptr->val;
}
conn_opt_ptr++;
}
keywords[opt_index] = NULL;
values[opt_index] = NULL;
rv = PQpingParams(keywords, values, 1);
if (!quiet)
{
printf("%s:%s - ", pghost, pgport);
switch (rv)
{
case PQPING_OK:
printf("accepting connections\n");
break;
case PQPING_REJECT:
printf("rejecting connections\n");
break;
case PQPING_NO_RESPONSE:
printf("no response\n");
break;
case PQPING_NO_ATTEMPT:
printf("no attempt\n");
break;
default:
printf("unknown\n");
}
}
PQconninfoFree(connect_options);
exit(rv);
}
static void
help(const char *progname)
{
printf(_("%s issues a connection check to a PostgreSQL database.\n\n"), progname);
printf(_("Usage:\n"));
printf(_(" %s [OPTION]...\n"), progname);
printf(_("\nOptions:\n"));
printf(_(" -d, --dbname=DBNAME database name\n"));
printf(_(" -q, --quiet run quietly\n"));
printf(_(" -V, --version output version information, then exit\n"));
printf(_(" -?, --help show this help, then exit\n"));
printf(_("\nConnection options:\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
printf(_(" -p, --port=PORT database server port\n"));
printf(_(" -U, --username=USERNAME database username\n"));
}
...@@ -110,6 +110,11 @@ typedef enum ...@@ -110,6 +110,11 @@ typedef enum
PQERRORS_VERBOSE /* all the facts, ma'am */ PQERRORS_VERBOSE /* all the facts, ma'am */
} PGVerbosity; } PGVerbosity;
/*
* PGPing - The ordering of this enum should not be altered because the
* values are exposed externally via pg_isready.
*/
typedef enum typedef enum
{ {
PQPING_OK, /* server is accepting connections */ PQPING_OK, /* server is accepting connections */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment