Age Owner Branch data TLA Line data Source code
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
4099 rhaas@postgresql.org 23 :CBC 5 : main(int argc, char **argv)
24 : : {
25 : : int c;
26 : :
27 : : const char *progname;
28 : :
29 : 5 : const char *pghost = NULL;
30 : 5 : const char *pgport = NULL;
31 : 5 : const char *pguser = NULL;
32 : 5 : const char *pgdbname = NULL;
4097 33 : 5 : const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
34 : :
3960 fujii@postgresql.org 35 : 5 : const char *pghost_str = NULL;
3797 36 : 5 : const char *pghostaddr_str = NULL;
3960 37 : 5 : 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 : :
3973 bruce@momjian.us 44 : 5 : bool quiet = false;
45 : :
46 : : PGPing rv;
3960 fujii@postgresql.org 47 : 5 : PQconninfoOption *opts = NULL;
48 : 5 : PQconninfoOption *defs = NULL;
49 : : PQconninfoOption *opt;
50 : : PQconninfoOption *def;
51 : 5 : 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 : :
1840 peter@eisentraut.org 68 : 5 : pg_logging_init(argv[0]);
4099 rhaas@postgresql.org 69 : 5 : progname = get_progname(argv[0]);
4097 70 : 5 : set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
4099 71 : 5 : handle_help_version_opts(argc, argv, progname, help);
72 : :
3960 fujii@postgresql.org 73 [ + + ]: 4 : while ((c = getopt_long(argc, argv, "d:h:p:qt:U:", long_options, NULL)) != -1)
74 : : {
4099 rhaas@postgresql.org 75 [ - - - - : 2 : switch (c)
+ - + ]
76 : : {
4099 rhaas@postgresql.org 77 :UBC 0 : case 'd':
78 : 0 : pgdbname = pg_strdup(optarg);
79 : 0 : break;
80 : 0 : case 'h':
81 : 0 : pghost = pg_strdup(optarg);
82 : 0 : break;
83 : 0 : case 'p':
84 : 0 : pgport = pg_strdup(optarg);
85 : 0 : break;
86 : 0 : case 'q':
87 : 0 : quiet = true;
88 : 0 : break;
4097 rhaas@postgresql.org 89 :CBC 1 : case 't':
90 : 1 : connect_timeout = pg_strdup(optarg);
91 : 1 : break;
4099 rhaas@postgresql.org 92 :UBC 0 : case 'U':
93 : 0 : pguser = pg_strdup(optarg);
94 : 0 : break;
4099 rhaas@postgresql.org 95 :CBC 1 : default:
96 : : /* getopt_long already emitted a complaint */
737 tgl@sss.pgh.pa.us 97 : 1 : 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 : : */
4099 rhaas@postgresql.org 103 : 1 : exit(PQPING_NO_ATTEMPT);
104 : : }
105 : : }
106 : :
107 [ - + ]: 2 : if (optind < argc)
108 : : {
1840 peter@eisentraut.org 109 :UBC 0 : pg_log_error("too many command-line arguments (first is \"%s\")",
110 : : argv[optind]);
737 tgl@sss.pgh.pa.us 111 : 0 : 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 : : */
4099 rhaas@postgresql.org 117 : 0 : exit(PQPING_NO_ATTEMPT);
118 : : }
119 : :
3960 fujii@postgresql.org 120 :CBC 2 : keywords[0] = "host";
121 : 2 : values[0] = pghost;
122 : 2 : keywords[1] = "port";
123 : 2 : values[1] = pgport;
124 : 2 : keywords[2] = "user";
125 : 2 : values[2] = pguser;
126 : 2 : keywords[3] = "dbname";
127 : 2 : values[3] = pgdbname;
128 : 2 : keywords[4] = "connect_timeout";
129 : 2 : values[4] = connect_timeout;
130 : 2 : keywords[5] = "fallback_application_name";
131 : 2 : values[5] = progname;
132 : 2 : keywords[6] = NULL;
133 : 2 : values[6] = NULL;
134 : :
135 : : /*
136 : : * Get the host and port so we can display them in our output
137 : : */
3797 138 [ - + ]: 2 : if (pgdbname &&
3797 fujii@postgresql.org 139 [ # # ]:UBC 0 : (strncmp(pgdbname, "postgresql://", 13) == 0 ||
140 [ # # ]: 0 : strncmp(pgdbname, "postgres://", 11) == 0 ||
141 [ # # ]: 0 : strchr(pgdbname, '=') != NULL))
142 : : {
3960 143 : 0 : opts = PQconninfoParse(pgdbname, &errmsg);
144 [ # # ]: 0 : if (opts == NULL)
145 : : {
1840 peter@eisentraut.org 146 : 0 : pg_log_error("%s", errmsg);
3960 fujii@postgresql.org 147 : 0 : exit(PQPING_NO_ATTEMPT);
148 : : }
149 : : }
150 : :
3960 fujii@postgresql.org 151 :CBC 2 : defs = PQconndefaults();
152 [ - + ]: 2 : if (defs == NULL)
153 : : {
1840 peter@eisentraut.org 154 :UBC 0 : pg_log_error("could not fetch default options");
3960 fujii@postgresql.org 155 : 0 : exit(PQPING_NO_ATTEMPT);
156 : : }
157 : :
3960 fujii@postgresql.org 158 [ + + ]:CBC 84 : for (opt = opts, def = defs; def->keyword; def++)
159 : : {
3797 160 [ + + ]: 82 : if (strcmp(def->keyword, "host") == 0)
161 : : {
3960 162 [ - + - - ]: 2 : if (opt && opt->val)
3960 fujii@postgresql.org 163 :UBC 0 : pghost_str = opt->val;
3960 fujii@postgresql.org 164 [ - + ]:CBC 2 : else if (pghost)
3960 fujii@postgresql.org 165 :UBC 0 : pghost_str = pghost;
3960 fujii@postgresql.org 166 [ + - ]:CBC 2 : else if (def->val)
167 : 2 : pghost_str = def->val;
168 : : else
3960 fujii@postgresql.org 169 :UBC 0 : pghost_str = DEFAULT_PGSOCKET_DIR;
170 : : }
3797 fujii@postgresql.org 171 [ + + ]:CBC 80 : else if (strcmp(def->keyword, "hostaddr") == 0)
172 : : {
173 [ - + - - ]: 2 : if (opt && opt->val)
3797 fujii@postgresql.org 174 :UBC 0 : pghostaddr_str = opt->val;
3797 fujii@postgresql.org 175 [ - + ]:CBC 2 : else if (def->val)
3797 fujii@postgresql.org 176 :UBC 0 : pghostaddr_str = def->val;
177 : : }
3960 fujii@postgresql.org 178 [ + + ]:CBC 78 : else if (strcmp(def->keyword, "port") == 0)
179 : : {
180 [ - + - - ]: 2 : if (opt && opt->val)
3960 fujii@postgresql.org 181 :UBC 0 : pgport_str = opt->val;
3960 fujii@postgresql.org 182 [ - + ]:CBC 2 : else if (pgport)
3960 fujii@postgresql.org 183 :UBC 0 : pgport_str = pgport;
3960 fujii@postgresql.org 184 [ + - ]:CBC 2 : else if (def->val)
185 : 2 : pgport_str = def->val;
186 : : }
187 : :
188 [ - + ]: 82 : if (opt)
3960 fujii@postgresql.org 189 :UBC 0 : opt++;
190 : : }
191 : :
4099 rhaas@postgresql.org 192 :CBC 2 : rv = PQpingParams(keywords, values, 1);
193 : :
194 [ + - ]: 2 : if (!quiet)
195 : : {
3797 fujii@postgresql.org 196 [ - + ]: 2 : printf("%s:%s - ",
197 : : pghostaddr_str != NULL ? pghostaddr_str : pghost_str,
198 : : pgport_str);
199 : :
4099 rhaas@postgresql.org 200 [ + - + - : 2 : switch (rv)
- ]
201 : : {
202 : 1 : case PQPING_OK:
3425 fujii@postgresql.org 203 : 1 : printf(_("accepting connections\n"));
4099 rhaas@postgresql.org 204 : 1 : break;
4099 rhaas@postgresql.org 205 :UBC 0 : case PQPING_REJECT:
3425 fujii@postgresql.org 206 : 0 : printf(_("rejecting connections\n"));
4099 rhaas@postgresql.org 207 : 0 : break;
4099 rhaas@postgresql.org 208 :CBC 1 : case PQPING_NO_RESPONSE:
3425 fujii@postgresql.org 209 : 1 : printf(_("no response\n"));
4099 rhaas@postgresql.org 210 : 1 : break;
4099 rhaas@postgresql.org 211 :UBC 0 : case PQPING_NO_ATTEMPT:
3425 fujii@postgresql.org 212 : 0 : printf(_("no attempt\n"));
4099 rhaas@postgresql.org 213 : 0 : break;
214 : 0 : default:
3425 fujii@postgresql.org 215 : 0 : printf(_("unknown\n"));
216 : : }
217 : : }
218 : :
4099 rhaas@postgresql.org 219 :CBC 2 : exit(rv);
220 : : }
221 : :
222 : : static void
223 : 1 : help(const char *progname)
224 : : {
225 : 1 : printf(_("%s issues a connection check to a PostgreSQL database.\n\n"), progname);
226 : 1 : printf(_("Usage:\n"));
227 : 1 : printf(_(" %s [OPTION]...\n"), progname);
228 : :
229 : 1 : printf(_("\nOptions:\n"));
230 : 1 : printf(_(" -d, --dbname=DBNAME database name\n"));
231 : 1 : printf(_(" -q, --quiet run quietly\n"));
232 : 1 : printf(_(" -V, --version output version information, then exit\n"));
233 : 1 : printf(_(" -?, --help show this help, then exit\n"));
234 : :
235 : 1 : printf(_("\nConnection options:\n"));
236 : 1 : printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
237 : 1 : printf(_(" -p, --port=PORT database server port\n"));
4097 238 : 1 : printf(_(" -t, --timeout=SECS seconds to wait when attempting connection, 0 disables (default: %s)\n"), DEFAULT_CONNECT_TIMEOUT);
3934 peter_e@gmx.net 239 : 1 : printf(_(" -U, --username=USERNAME user name to connect as\n"));
1507 peter@eisentraut.org 240 : 1 : printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
241 : 1 : printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
4099 rhaas@postgresql.org 242 : 1 : }
|