PostgreSQL Source Code  git master
pg_isready.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pg_isready --- checks the status of the PostgreSQL server
4  *
5  * Copyright (c) 2013-2024, PostgreSQL Global Development Group
6  *
7  * src/bin/scripts/pg_isready.c
8  *
9  *-------------------------------------------------------------------------
10  */
11 
12 #include "postgres_fe.h"
13 #include "common.h"
14 #include "common/logging.h"
15 #include "fe_utils/option_utils.h"
16 
17 #define DEFAULT_CONNECT_TIMEOUT "3"
18 
19 static void
20  help(const char *progname);
21 
22 int
23 main(int argc, char **argv)
24 {
25  int c;
26 
27  const char *progname;
28 
29  const char *pghost = NULL;
30  const char *pgport = NULL;
31  const char *pguser = NULL;
32  const char *pgdbname = NULL;
33  const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
34 
35  const char *pghost_str = NULL;
36  const char *pghostaddr_str = NULL;
37  const char *pgport_str = NULL;
38 
39 #define PARAMS_ARRAY_SIZE 7
40 
41  const char *keywords[PARAMS_ARRAY_SIZE];
42  const char *values[PARAMS_ARRAY_SIZE];
43 
44  bool quiet = false;
45 
46  PGPing rv;
47  PQconninfoOption *opts = NULL;
48  PQconninfoOption *defs = NULL;
49  PQconninfoOption *opt;
50  PQconninfoOption *def;
51  char *errmsg = NULL;
52 
53  /*
54  * We accept user and database as options to avoid useless errors from
55  * connecting with invalid params
56  */
57 
58  static struct option long_options[] = {
59  {"dbname", required_argument, NULL, 'd'},
60  {"host", required_argument, NULL, 'h'},
61  {"port", required_argument, NULL, 'p'},
62  {"quiet", no_argument, NULL, 'q'},
63  {"timeout", required_argument, NULL, 't'},
64  {"username", required_argument, NULL, 'U'},
65  {NULL, 0, NULL, 0}
66  };
67 
68  pg_logging_init(argv[0]);
69  progname = get_progname(argv[0]);
70  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
72 
73  while ((c = getopt_long(argc, argv, "d:h:p:qt:U:", long_options, NULL)) != -1)
74  {
75  switch (c)
76  {
77  case 'd':
78  pgdbname = pg_strdup(optarg);
79  break;
80  case 'h':
82  break;
83  case 'p':
85  break;
86  case 'q':
87  quiet = true;
88  break;
89  case 't':
90  connect_timeout = pg_strdup(optarg);
91  break;
92  case 'U':
93  pguser = pg_strdup(optarg);
94  break;
95  default:
96  /* getopt_long already emitted a complaint */
97  pg_log_error_hint("Try \"%s --help\" for more information.", progname);
98 
99  /*
100  * We need to make sure we don't return 1 here because someone
101  * checking the return code might infer unintended meaning
102  */
104  }
105  }
106 
107  if (optind < argc)
108  {
109  pg_log_error("too many command-line arguments (first is \"%s\")",
110  argv[optind]);
111  pg_log_error_hint("Try \"%s --help\" for more information.", progname);
112 
113  /*
114  * We need to make sure we don't return 1 here because someone
115  * checking the return code might infer unintended meaning
116  */
118  }
119 
120  keywords[0] = "host";
121  values[0] = pghost;
122  keywords[1] = "port";
123  values[1] = pgport;
124  keywords[2] = "user";
125  values[2] = pguser;
126  keywords[3] = "dbname";
127  values[3] = pgdbname;
128  keywords[4] = "connect_timeout";
129  values[4] = connect_timeout;
130  keywords[5] = "fallback_application_name";
131  values[5] = progname;
132  keywords[6] = NULL;
133  values[6] = NULL;
134 
135  /*
136  * Get the host and port so we can display them in our output
137  */
138  if (pgdbname &&
139  (strncmp(pgdbname, "postgresql://", 13) == 0 ||
140  strncmp(pgdbname, "postgres://", 11) == 0 ||
141  strchr(pgdbname, '=') != NULL))
142  {
143  opts = PQconninfoParse(pgdbname, &errmsg);
144  if (opts == NULL)
145  {
146  pg_log_error("%s", errmsg);
148  }
149  }
150 
151  defs = PQconndefaults();
152  if (defs == NULL)
153  {
154  pg_log_error("could not fetch default options");
156  }
157 
158  for (opt = opts, def = defs; def->keyword; def++)
159  {
160  if (strcmp(def->keyword, "host") == 0)
161  {
162  if (opt && opt->val)
163  pghost_str = opt->val;
164  else if (pghost)
165  pghost_str = pghost;
166  else if (def->val)
167  pghost_str = def->val;
168  else
169  pghost_str = DEFAULT_PGSOCKET_DIR;
170  }
171  else if (strcmp(def->keyword, "hostaddr") == 0)
172  {
173  if (opt && opt->val)
174  pghostaddr_str = opt->val;
175  else if (def->val)
176  pghostaddr_str = def->val;
177  }
178  else if (strcmp(def->keyword, "port") == 0)
179  {
180  if (opt && opt->val)
181  pgport_str = opt->val;
182  else if (pgport)
183  pgport_str = pgport;
184  else if (def->val)
185  pgport_str = def->val;
186  }
187 
188  if (opt)
189  opt++;
190  }
191 
192  rv = PQpingParams(keywords, values, 1);
193 
194  if (!quiet)
195  {
196  printf("%s:%s - ",
197  pghostaddr_str != NULL ? pghostaddr_str : pghost_str,
198  pgport_str);
199 
200  switch (rv)
201  {
202  case PQPING_OK:
203  printf(_("accepting connections\n"));
204  break;
205  case PQPING_REJECT:
206  printf(_("rejecting connections\n"));
207  break;
208  case PQPING_NO_RESPONSE:
209  printf(_("no response\n"));
210  break;
211  case PQPING_NO_ATTEMPT:
212  printf(_("no attempt\n"));
213  break;
214  default:
215  printf(_("unknown\n"));
216  }
217  }
218 
219  exit(rv);
220 }
221 
222 static void
223 help(const char *progname)
224 {
225  printf(_("%s issues a connection check to a PostgreSQL database.\n\n"), progname);
226  printf(_("Usage:\n"));
227  printf(_(" %s [OPTION]...\n"), progname);
228 
229  printf(_("\nOptions:\n"));
230  printf(_(" -d, --dbname=DBNAME database name\n"));
231  printf(_(" -q, --quiet run quietly\n"));
232  printf(_(" -V, --version output version information, then exit\n"));
233  printf(_(" -?, --help show this help, then exit\n"));
234 
235  printf(_("\nConnection options:\n"));
236  printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
237  printf(_(" -p, --port=PORT database server port\n"));
238  printf(_(" -t, --timeout=SECS seconds to wait when attempting connection, 0 disables (default: %s)\n"), DEFAULT_CONNECT_TIMEOUT);
239  printf(_(" -U, --username=USERNAME user name to connect as\n"));
240  printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
241  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
242 }
static Datum values[MAXATTR]
Definition: bootstrap.c:152
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1201
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:448
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define _(x)
Definition: elog.c:90
PQconninfoOption * PQconninfoParse(const char *conninfo, char **errmsg)
Definition: fe-connect.c:5529
PQconninfoOption * PQconndefaults(void)
Definition: fe-connect.c:1819
PGPing PQpingParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:696
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:60
#define no_argument
Definition: getopt_long.h:24
#define required_argument
Definition: getopt_long.h:25
PGPing
Definition: libpq-fe.h:149
@ PQPING_OK
Definition: libpq-fe.h:150
@ PQPING_REJECT
Definition: libpq-fe.h:151
@ PQPING_NO_RESPONSE
Definition: libpq-fe.h:152
@ PQPING_NO_ATTEMPT
Definition: libpq-fe.h:153
exit(1)
void pg_logging_init(const char *argv0)
Definition: logging.c:83
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_error_hint(...)
Definition: logging.h:112
const char * progname
Definition: main.c:44
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
Definition: option_utils.c:24
static AmcheckOptions opts
Definition: pg_amcheck.c:111
#define DEFAULT_PGSOCKET_DIR
PGDLLIMPORT int optind
Definition: getopt.c:50
PGDLLIMPORT char * optarg
Definition: getopt.c:52
static void help(const char *progname)
Definition: pg_isready.c:223
int main(int argc, char **argv)
Definition: pg_isready.c:23
#define PARAMS_ARRAY_SIZE
#define DEFAULT_CONNECT_TIMEOUT
Definition: pg_isready.c:17
const char * pghost
Definition: pgbench.c:294
const char * pgport
Definition: pgbench.c:295
const char * get_progname(const char *argv0)
Definition: path.c:574
#define printf(...)
Definition: port.h:244
char * c