PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/ext/common/agents/HelperAgent/OptionParser.h

http://github.com/FooBarWidget/passenger
C Header | 378 lines | 335 code | 12 blank | 31 comment | 104 complexity | 26f3d4d296bf529246bca5441b53d8bf MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause, ISC
  1. /*
  2. * Phusion Passenger - https://www.phusionpassenger.com/
  3. * Copyright (c) 2010-2015 Phusion
  4. *
  5. * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #ifndef _PASSENGER_SERVER_OPTION_PARSER_H_
  26. #define _PASSENGER_SERVER_OPTION_PARSER_H_
  27. #include <boost/thread.hpp>
  28. #include <cstdio>
  29. #include <cstdlib>
  30. #include <Constants.h>
  31. #include <Utils.h>
  32. #include <Utils/VariantMap.h>
  33. #include <Utils/OptionParsing.h>
  34. #include <Utils/StrIntUtils.h>
  35. namespace Passenger {
  36. using namespace std;
  37. inline void
  38. serverUsage() {
  39. // ....|---------------Keep output within standard terminal width (80 chars)------------|
  40. printf("Usage: " AGENT_EXE " server <OPTIONS...> [APP DIRECTORY]\n");
  41. printf("Runs the " PROGRAM_NAME " standalone HTTP server agent.\n");
  42. printf("\n");
  43. printf("The server starts in single-app mode, unless --multi-app is specified. When\n");
  44. printf("in single-app mode, it serves the app at the current working directory, or the\n");
  45. printf("app specified by APP DIRECTORY.\n");
  46. printf("\n");
  47. printf("Required options:\n");
  48. printf(" --passenger-root PATH The location to the " PROGRAM_NAME " source\n");
  49. printf(" directory\n");
  50. printf("\n");
  51. printf("Socket options (optional):\n");
  52. printf(" -l, --listen ADDRESS Listen on the given address. The address must be\n");
  53. printf(" formatted as tcp://IP:PORT for TCP sockets, or\n");
  54. printf(" unix:PATH for Unix domain sockets. You can specify\n");
  55. printf(" this option multiple times (up to %u times) to\n",
  56. SERVER_KIT_MAX_SERVER_ENDPOINTS);
  57. printf(" listen on multiple addresses. Default:\n");
  58. printf(" " DEFAULT_HTTP_SERVER_LISTEN_ADDRESS "\n");
  59. printf(" --admin-listen ADDRESS\n");
  60. printf(" Listen on the given address for admin commands.\n");
  61. printf(" The same syntax and limitations as with --listen\n");
  62. printf(" are applicable\n");
  63. printf("\n");
  64. printf("Daemon options (optional):\n");
  65. printf(" --pid-file PATH Store the server's PID in the given file. The file\n");
  66. printf(" is deleted on exit\n");
  67. printf("\n");
  68. printf("Security options (optional):\n");
  69. printf(" --multi-app-password-file PATH\n");
  70. printf(" Password-protect access to the HTTP server\n");
  71. printf(" (multi-app mode only)\n");
  72. printf(" --authorize [LEVEL]:USERNAME:PASSWORDFILE\n");
  73. printf(" Enables authentication on the admin server, through\n");
  74. printf(" the given admin account. LEVEL indicates the\n");
  75. printf(" privilege level (see below). PASSWORDFILE must\n");
  76. printf(" point to a file containing the password\n");
  77. printf(" --no-user-switching Disables user switching support\n");
  78. printf(" --default-user NAME Default user to start apps as, when user\n");
  79. printf(" switching is enabled. Default: " DEFAULT_WEB_APP_USER "\n");
  80. printf(" --default-group NAME Default group to start apps as, when user\n");
  81. printf(" switching is disabled. Default: the default\n");
  82. printf(" user's primary group\n");
  83. printf("\n");
  84. printf("Application serving options (optional):\n");
  85. printf(" -e, --environment NAME Default framework environment name to use.\n");
  86. printf(" Default: " DEFAULT_APP_ENV "\n");
  87. printf(" --app-type TYPE The type of application you want to serve\n");
  88. printf(" (single-app mode only)\n");
  89. printf(" --startup-file PATH The path of the app's startup file, relative to\n");
  90. printf(" the app root directory (single-app mode only)\n");
  91. printf(" --spawn-method NAME Spawn method to use. Can either be 'smart' or\n");
  92. printf(" 'direct'. Default: %s\n", DEFAULT_SPAWN_METHOD);
  93. printf(" --load-shell-envvars Load shell startup files before loading application\n");
  94. printf(" --concurrency-model The concurrency model to use for the app, either\n");
  95. printf(" 'process' or 'thread' (Enterprise only).\n");
  96. printf(" Default: " DEFAULT_CONCURRENCY_MODEL "\n");
  97. printf(" --app-thread-count The number of application threads to use when using\n");
  98. printf(" the 'thread' concurrency model (Enterprise only).\n");
  99. printf(" Default: %d\n", DEFAULT_APP_THREAD_COUNT);
  100. printf("\n");
  101. printf(" --multi-app Enable multi-app mode\n");
  102. printf("\n");
  103. printf(" --force-friendly-error-pages\n");
  104. printf(" Force friendly error pages to be always on\n");
  105. printf(" --disable-friendly-error-pages\n");
  106. printf(" Force friendly error pages to be always off\n");
  107. printf("\n");
  108. printf(" --ruby PATH Default Ruby interpreter to use.\n");
  109. printf(" --nodejs PATH Default NodeJs interpreter to use.\n");
  110. printf(" --python PATH Default Python interpreter to use.\n");
  111. printf(" --meteor-app-settings PATH\n");
  112. printf(" File with settings for a Meteor (non-bundled) app.\n");
  113. printf(" (passed to Meteor using --settings)\n");
  114. printf(" --debugger Enable Ruby debugger support (Enterprise only)\n");
  115. printf("\n");
  116. printf(" --rolling-restarts Enable rolling restarts (Enterprise only)\n");
  117. printf(" --resist-deployment-errors\n");
  118. printf(" Enable deployment error resistance (Enterprise only)\n");
  119. printf("\n");
  120. printf("Process management options (optional):\n");
  121. printf(" --max-pool-size N Maximum number of application processes.\n");
  122. printf(" Default: %d\n", DEFAULT_MAX_POOL_SIZE);
  123. printf(" --pool-idle-time SECS\n");
  124. printf(" Maximum number of seconds an application process\n");
  125. printf(" may be idle. Default: %d\n", DEFAULT_POOL_IDLE_TIME);
  126. printf(" --min-instances N Minimum number of application processes. Default: 1\n");
  127. printf("\n");
  128. printf("Request handling options (optional):\n");
  129. printf(" --max-request-time Abort requests that take too much time (Enterprise\n");
  130. printf(" only)\n");
  131. printf(" --sticky-sessions Enable sticky sessions\n");
  132. printf(" --sticky-sessions-cookie-name NAME\n");
  133. printf(" Cookie name to use for sticky sessions.\n");
  134. printf(" Default: " DEFAULT_STICKY_SESSIONS_COOKIE_NAME "\n");
  135. printf(" --vary-turbocache-by-cookie NAME\n");
  136. printf(" Vary the turbocache by the cookie of the given name\n");
  137. printf(" --disable-turbocaching\n");
  138. printf(" Disable turbocaching\n");
  139. printf("\n");
  140. printf("Other options (optional):\n");
  141. printf(" --log-file PATH Log to the given file.\n");
  142. printf(" --log-level LEVEL Logging level. Default: %d\n", DEFAULT_LOG_LEVEL);
  143. printf(" --fd-log-file PATH Log file descriptor activity to the given file.\n");
  144. printf(" --stat-throttle-rate SECONDS\n");
  145. printf(" Throttle filesystem restart.txt checks to at most\n");
  146. printf(" once per given seconds. Default: %d\n", DEFAULT_STAT_THROTTLE_RATE);
  147. printf(" --no-show-version-in-header\n");
  148. printf(" Do not show " PROGRAM_NAME " version number in\n");
  149. printf(" HTTP headers.\n");
  150. printf(" --data-buffer-dir PATH\n");
  151. printf(" Directory to store data buffers in. Default:\n");
  152. printf(" %s\n", getSystemTempDir());
  153. printf(" --no-graceful-exit When exiting, exit immediately instead of waiting\n");
  154. printf(" for all connections to terminate\n");
  155. printf(" --benchmark MODE Enable benchmark mode. Available modes:\n");
  156. printf(" after_accept,before_checkout,after_checkout,\n");
  157. printf(" response_begin\n");
  158. printf(" --disable-selfchecks Disable various self-checks. This improves\n");
  159. printf(" performance, but might delay finding bugs in\n");
  160. printf(" " PROGRAM_NAME "\n");
  161. printf(" --threads NUMBER Number of threads to use for request handling.\n");
  162. printf(" Default: number of CPU cores (%d)\n",
  163. boost::thread::hardware_concurrency());
  164. printf(" --cpu-affine Enable per-thread CPU affinity (Linux only)\n");
  165. printf(" -h, --help Show this help\n");
  166. printf("\n");
  167. printf("Admin account privilege levels (ordered from most to least privileges):\n");
  168. printf(" readonly Read-only access\n");
  169. printf(" full Full access (default)\n");
  170. }
  171. inline bool
  172. parseServerOption(int argc, const char *argv[], int &i, VariantMap &options) {
  173. OptionParser p(serverUsage);
  174. if (p.isValueFlag(argc, i, argv[i], '\0', "--passenger-root")) {
  175. options.set("passenger_root", argv[i + 1]);
  176. i += 2;
  177. } else if (p.isValueFlag(argc, i, argv[i], 'l', "--listen")) {
  178. if (getSocketAddressType(argv[i + 1]) != SAT_UNKNOWN) {
  179. vector<string> addresses = options.getStrSet("server_addresses", false);
  180. if (addresses.size() == SERVER_KIT_MAX_SERVER_ENDPOINTS) {
  181. fprintf(stderr, "ERROR: you may specify up to %u --listen addresses.\n",
  182. SERVER_KIT_MAX_SERVER_ENDPOINTS);
  183. exit(1);
  184. }
  185. addresses.push_back(argv[i + 1]);
  186. options.setStrSet("server_addresses", addresses);
  187. i += 2;
  188. } else {
  189. fprintf(stderr, "ERROR: invalid address format for --listen. The address "
  190. "must be formatted as tcp://IP:PORT for TCP sockets, or unix:PATH "
  191. "for Unix domain sockets.\n");
  192. exit(1);
  193. }
  194. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--admin-listen")) {
  195. if (getSocketAddressType(argv[i + 1]) != SAT_UNKNOWN) {
  196. vector<string> addresses = options.getStrSet("server_admin_addresses",
  197. false);
  198. if (addresses.size() == SERVER_KIT_MAX_SERVER_ENDPOINTS) {
  199. fprintf(stderr, "ERROR: you may specify up to %u --admin-listen addresses.\n",
  200. SERVER_KIT_MAX_SERVER_ENDPOINTS);
  201. exit(1);
  202. }
  203. addresses.push_back(argv[i + 1]);
  204. options.setStrSet("server_admin_addresses", addresses);
  205. i += 2;
  206. } else {
  207. fprintf(stderr, "ERROR: invalid address format for --admin-listen. The address "
  208. "must be formatted as tcp://IP:PORT for TCP sockets, or unix:PATH "
  209. "for Unix domain sockets.\n");
  210. exit(1);
  211. }
  212. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--pid-file")) {
  213. options.set("server_pid_file", argv[i + 1]);
  214. i += 2;
  215. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--authorize")) {
  216. vector<string> args;
  217. vector<string> authorizations = options.getStrSet("server_authorizations",
  218. false);
  219. split(argv[i + 1], ':', args);
  220. if (args.size() < 2 || args.size() > 3) {
  221. fprintf(stderr, "ERROR: invalid format for --authorize. The syntax "
  222. "is \"[LEVEL:]USERNAME:PASSWORDFILE\".\n");
  223. exit(1);
  224. }
  225. authorizations.push_back(argv[i + 1]);
  226. options.setStrSet("server_authorizations", authorizations);
  227. i += 2;
  228. } else if (p.isFlag(argv[i], '\0', "--no-user-switching")) {
  229. options.setBool("user_switching", false);
  230. i++;
  231. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--default-user")) {
  232. options.set("default_user", argv[i + 1]);
  233. i += 2;
  234. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--default-group")) {
  235. options.set("default_group", argv[i + 1]);
  236. i += 2;
  237. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--max-pool-size")) {
  238. options.setInt("max_pool_size", atoi(argv[i + 1]));
  239. i += 2;
  240. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--pool-idle-time")) {
  241. options.setInt("pool_idle_time", atoi(argv[i + 1]));
  242. i += 2;
  243. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--min-instances")) {
  244. options.setInt("min_instances", atoi(argv[i + 1]));
  245. i += 2;
  246. } else if (p.isValueFlag(argc, i, argv[i], 'e', "--environment")) {
  247. options.set("environment", argv[i + 1]);
  248. i += 2;
  249. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--app-type")) {
  250. options.set("app_type", argv[i + 1]);
  251. i += 2;
  252. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--startup-file")) {
  253. options.set("startup_file", argv[i + 1]);
  254. i += 2;
  255. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--spawn-method")) {
  256. options.set("spawn_method", argv[i + 1]);
  257. i += 2;
  258. } else if (p.isFlag(argv[i], '\0', "--load-shell-envvars")) {
  259. options.setBool("load_shell_envvars", true);
  260. i++;
  261. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--concurrency-model")) {
  262. options.set("concurrency_model", argv[i + 1]);
  263. i += 2;
  264. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--app-thread-count")) {
  265. options.setInt("app_thread_count", atoi(argv[i + 1]));
  266. i += 2;
  267. } else if (p.isFlag(argv[i], '\0', "--multi-app")) {
  268. options.setBool("multi_app", true);
  269. i++;
  270. } else if (p.isFlag(argv[i], '\0', "--force-friendly-error-pages")) {
  271. options.setBool("friendly_error_pages", true);
  272. i++;
  273. } else if (p.isFlag(argv[i], '\0', "--disable-friendly-error-pages")) {
  274. options.setBool("friendly_error_pages", false);
  275. i++;
  276. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--max-request-time")) {
  277. options.setInt("max_request_time", atoi(argv[i + 1]));
  278. i += 2;
  279. } else if (p.isFlag(argv[i], '\0', "--sticky-sessions")) {
  280. options.setBool("sticky_sessions", true);
  281. i++;
  282. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--sticky-sessions-cookie-name")) {
  283. options.set("sticky_sessions_cookie_name", argv[i + 1]);
  284. i += 2;
  285. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--vary-turbocache-by-cookie")) {
  286. options.set("vary_turbocache_by_cookie", argv[i + 1]);
  287. i += 2;
  288. } else if (p.isFlag(argv[i], '\0', "--disable-turbocaching")) {
  289. options.setBool("turbocaching", false);
  290. i++;
  291. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--ruby")) {
  292. options.set("default_ruby", argv[i + 1]);
  293. i += 2;
  294. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--nodejs")) {
  295. options.set("default_nodejs", argv[i + 1]);
  296. i += 2;
  297. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--python")) {
  298. options.set("default_python", argv[i + 1]);
  299. i += 2;
  300. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--meteor-app-settings")) {
  301. options.set("meteor_app_settings", argv[i + 1]);
  302. i += 2;
  303. } else if (p.isFlag(argv[i], '\0', "--debugger")) {
  304. options.setBool("debugger", true);
  305. i++;
  306. } else if (p.isFlag(argv[i], '\0', "--rolling-restarts")) {
  307. options.setBool("rolling_restarts", true);
  308. i++;
  309. } else if (p.isFlag(argv[i], '\0', "--resist-deployment-errors")) {
  310. options.setBool("resist_deployment_errors", true);
  311. i++;
  312. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--log-level")) {
  313. // We do not set log_level because, when this function is called from
  314. // the Watchdog, we don't want to affect the Watchdog's own log level.
  315. options.setInt("server_log_level", atoi(argv[i + 1]));
  316. i += 2;
  317. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--log-file")) {
  318. // We do not set log_file because, when this function is called from
  319. // the Watchdog, we don't want to affect the Watchdog's own log file.
  320. options.set("server_log_file", argv[i + 1]);
  321. i += 2;
  322. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--fd-log-file")) {
  323. // We do not set file_descriptor_log_file because, when this function is called from
  324. // the Watchdog, we don't want to affect the Watchdog's own log file.
  325. options.set("server_file_descriptor_log_file", argv[i + 1]);
  326. i += 2;
  327. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--stat-throttle-rate")) {
  328. options.setInt("stat_throttle_rate", atoi(argv[i + 1]));
  329. i += 2;
  330. } else if (p.isFlag(argv[i], '\0', "--no-show-version-in-header")) {
  331. options.setBool("show_version_in_header", false);
  332. i++;
  333. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--data-buffer-dir")) {
  334. options.setInt("data_buffer_dir", atoi(argv[i + 1]));
  335. i += 2;
  336. } else if (p.isFlag(argv[i], '\0', "--no-graceful-exit")) {
  337. options.setBool("server_graceful_exit", false);
  338. i++;
  339. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--benchmark")) {
  340. options.set("benchmark_mode", argv[i + 1]);
  341. i += 2;
  342. } else if (p.isFlag(argv[i], '\0', "--disable-selfchecks")) {
  343. options.setBool("selfchecks", false);
  344. i++;
  345. } else if (p.isValueFlag(argc, i, argv[i], '\0', "--threads")) {
  346. options.setInt("server_threads", atoi(argv[i + 1]));
  347. i += 2;
  348. } else if (p.isFlag(argv[i], '\0', "--cpu-affine")) {
  349. options.setBool("server_cpu_affine", true);
  350. i++;
  351. } else if (!startsWith(argv[i], "-")) {
  352. if (!options.has("app_root")) {
  353. options.set("app_root", argv[i]);
  354. i++;
  355. } else {
  356. fprintf(stderr, "ERROR: you may not pass multiple application directories. "
  357. "Please type '%s server --help' for usage.\n", argv[0]);
  358. exit(1);
  359. }
  360. } else {
  361. return false;
  362. }
  363. return true;
  364. }
  365. } // namespace Passenger
  366. #endif /* _PASSENGER_SERVER_OPTION_PARSER_H_ */