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