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-2021, 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"));
71  handle_help_version_opts(argc, argv, progname, help);
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':
81  pghost = pg_strdup(optarg);
82  break;
83  case 'p':
84  pgport = pg_strdup(optarg);
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  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
97 
98  /*
99  * We need to make sure we don't return 1 here because someone
100  * checking the return code might infer unintended meaning
101  */
102  exit(PQPING_NO_ATTEMPT);
103  }
104  }
105 
106  if (optind < argc)
107  {
108  pg_log_error("too many command-line arguments (first is \"%s\")",
109  argv[optind]);
110  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
111 
112  /*
113  * We need to make sure we don't return 1 here because someone
114  * checking the return code might infer unintended meaning
115  */
116  exit(PQPING_NO_ATTEMPT);
117  }
118 
119  keywords[0] = "host";
120  values[0] = pghost;
121  keywords[1] = "port";
122  values[1] = pgport;
123  keywords[2] = "user";
124  values[2] = pguser;
125  keywords[3] = "dbname";
126  values[3] = pgdbname;
127  keywords[4] = "connect_timeout";
128  values[4] = connect_timeout;
129  keywords[5] = "fallback_application_name";
130  values[5] = progname;
131  keywords[6] = NULL;
132  values[6] = NULL;
133 
134  /*
135  * Get the host and port so we can display them in our output
136  */
137  if (pgdbname &&
138  (strncmp(pgdbname, "postgresql://", 13) == 0 ||
139  strncmp(pgdbname, "postgres://", 11) == 0 ||
140  strchr(pgdbname, '=') != NULL))
141  {
142  opts = PQconninfoParse(pgdbname, &errmsg);
143  if (opts == NULL)
144  {
145  pg_log_error("%s", errmsg);
146  exit(PQPING_NO_ATTEMPT);
147  }
148  }
149 
150  defs = PQconndefaults();
151  if (defs == NULL)
152  {
153  pg_log_error("could not fetch default options");
154  exit(PQPING_NO_ATTEMPT);
155  }
156 
157  for (opt = opts, def = defs; def->keyword; def++)
158  {
159  if (strcmp(def->keyword, "host") == 0)
160  {
161  if (opt && opt->val)
162  pghost_str = opt->val;
163  else if (pghost)
164  pghost_str = pghost;
165  else if (def->val)
166  pghost_str = def->val;
167  else
168  pghost_str = DEFAULT_PGSOCKET_DIR;
169  }
170  else if (strcmp(def->keyword, "hostaddr") == 0)
171  {
172  if (opt && opt->val)
173  pghostaddr_str = opt->val;
174  else if (def->val)
175  pghostaddr_str = def->val;
176  }
177  else if (strcmp(def->keyword, "port") == 0)
178  {
179  if (opt && opt->val)
180  pgport_str = opt->val;
181  else if (pgport)
182  pgport_str = pgport;
183  else if (def->val)
184  pgport_str = def->val;
185  }
186 
187  if (opt)
188  opt++;
189  }
190 
191  rv = PQpingParams(keywords, values, 1);
192 
193  if (!quiet)
194  {
195  printf("%s:%s - ",
196  pghostaddr_str != NULL ? pghostaddr_str : pghost_str,
197  pgport_str);
198 
199  switch (rv)
200  {
201  case PQPING_OK:
202  printf(_("accepting connections\n"));
203  break;
204  case PQPING_REJECT:
205  printf(_("rejecting connections\n"));
206  break;
207  case PQPING_NO_RESPONSE:
208  printf(_("no response\n"));
209  break;
210  case PQPING_NO_ATTEMPT:
211  printf(_("no attempt\n"));
212  break;
213  default:
214  printf(_("unknown\n"));
215  }
216  }
217 
218  exit(rv);
219 }
220 
221 static void
222 help(const char *progname)
223 {
224  printf(_("%s issues a connection check to a PostgreSQL database.\n\n"), progname);
225  printf(_("Usage:\n"));
226  printf(_(" %s [OPTION]...\n"), progname);
227 
228  printf(_("\nOptions:\n"));
229  printf(_(" -d, --dbname=DBNAME database name\n"));
230  printf(_(" -q, --quiet run quietly\n"));
231  printf(_(" -V, --version output version information, then exit\n"));
232  printf(_(" -?, --help show this help, then exit\n"));
233 
234  printf(_("\nConnection options:\n"));
235  printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
236  printf(_(" -p, --port=PORT database server port\n"));
237  printf(_(" -t, --timeout=SECS seconds to wait when attempting connection, 0 disables (default: %s)\n"), DEFAULT_CONNECT_TIMEOUT);
238  printf(_(" -U, --username=USERNAME user name to connect as\n"));
239  printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
240  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
241 }
PGPing PQpingParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:681
const char * progname
Definition: main.c:46
#define PARAMS_ARRAY_SIZE
const char * get_progname(const char *argv0)
Definition: path.c:453
#define pg_log_error(...)
Definition: logging.h:80
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
static void help(const char *progname)
Definition: pg_isready.c:222
void pg_logging_init(const char *argv0)
Definition: logging.c:81
const char * pghost
Definition: pgbench.c:278
#define printf(...)
Definition: port.h:222
#define fprintf
Definition: port.h:220
#define required_argument
Definition: getopt_long.h:25
PQconninfoOption * PQconninfoParse(const char *conninfo, char **errmsg)
Definition: fe-connect.c:5328
int optind
Definition: getopt.c:50
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
Definition: option_utils.c:22
char * c
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static AmcheckOptions opts
Definition: pg_amcheck.c:110
#define no_argument
Definition: getopt_long.h:24
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1215
int main(int argc, char **argv)
Definition: pg_isready.c:23
PQconninfoOption * PQconndefaults(void)
Definition: fe-connect.c:1477
static Datum values[MAXATTR]
Definition: bootstrap.c:166
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:433
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * optarg
Definition: getopt.c:52
PGPing
Definition: libpq-fe.h:134
#define DEFAULT_CONNECT_TIMEOUT
Definition: pg_isready.c:17
#define _(x)
Definition: elog.c:89
const char * pgport
Definition: pgbench.c:279
#define DEFAULT_PGSOCKET_DIR