main.c 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "common.h"
  3. #include "buildinfo.h"
  4. #include "static_threads.h"
  5. int netdata_zero_metrics_enabled;
  6. int netdata_anonymous_statistics_enabled;
  7. struct netdata_static_thread *static_threads;
  8. struct config netdata_config = {
  9. .first_section = NULL,
  10. .last_section = NULL,
  11. .mutex = NETDATA_MUTEX_INITIALIZER,
  12. .index = {
  13. .avl_tree = {
  14. .root = NULL,
  15. .compar = appconfig_section_compare
  16. },
  17. .rwlock = AVL_LOCK_INITIALIZER
  18. }
  19. };
  20. void netdata_cleanup_and_exit(int ret) {
  21. // enabling this, is wrong
  22. // because the threads will be cancelled while cleaning up
  23. // netdata_exit = 1;
  24. error_log_limit_unlimited();
  25. info("EXIT: netdata prepares to exit with code %d...", ret);
  26. send_statistics("EXIT", ret?"ERROR":"OK","-");
  27. char agent_crash_file[FILENAME_MAX + 1];
  28. char agent_incomplete_shutdown_file[FILENAME_MAX + 1];
  29. snprintfz(agent_crash_file, FILENAME_MAX, "%s/.agent_crash", netdata_configured_varlib_dir);
  30. snprintfz(agent_incomplete_shutdown_file, FILENAME_MAX, "%s/.agent_incomplete_shutdown", netdata_configured_varlib_dir);
  31. (void) rename(agent_crash_file, agent_incomplete_shutdown_file);
  32. // cleanup/save the database and exit
  33. info("EXIT: cleaning up the database...");
  34. rrdhost_cleanup_all();
  35. if(!ret) {
  36. // exit cleanly
  37. // stop everything
  38. info("EXIT: stopping static threads...");
  39. #ifdef ENABLE_NEW_CLOUD_PROTOCOL
  40. aclk_sync_exit_all();
  41. #endif
  42. cancel_main_threads();
  43. // free the database
  44. info("EXIT: freeing database memory...");
  45. #ifdef ENABLE_DBENGINE
  46. rrdeng_prepare_exit(&multidb_ctx);
  47. #endif
  48. rrdhost_free_all();
  49. #ifdef ENABLE_DBENGINE
  50. rrdeng_exit(&multidb_ctx);
  51. #endif
  52. }
  53. sql_close_database();
  54. // unlink the pid
  55. if(pidfile[0]) {
  56. info("EXIT: removing netdata PID file '%s'...", pidfile);
  57. if(unlink(pidfile) != 0)
  58. error("EXIT: cannot unlink pidfile '%s'.", pidfile);
  59. }
  60. #ifdef ENABLE_HTTPS
  61. security_clean_openssl();
  62. #endif
  63. info("EXIT: all done - netdata is now exiting - bye bye...");
  64. (void) unlink(agent_incomplete_shutdown_file);
  65. exit(ret);
  66. }
  67. void web_server_threading_selection(void) {
  68. web_server_mode = web_server_mode_id(config_get(CONFIG_SECTION_WEB, "mode", web_server_mode_name(web_server_mode)));
  69. int static_threaded = (web_server_mode == WEB_SERVER_MODE_STATIC_THREADED);
  70. int i;
  71. for (i = 0; static_threads[i].name; i++) {
  72. if (static_threads[i].start_routine == socket_listen_main_static_threaded)
  73. static_threads[i].enabled = static_threaded;
  74. }
  75. }
  76. int make_dns_decision(const char *section_name, const char *config_name, const char *default_value, SIMPLE_PATTERN *p)
  77. {
  78. char *value = config_get(section_name,config_name,default_value);
  79. if(!strcmp("yes",value))
  80. return 1;
  81. if(!strcmp("no",value))
  82. return 0;
  83. if(strcmp("heuristic",value))
  84. error("Invalid configuration option '%s' for '%s'/'%s'. Valid options are 'yes', 'no' and 'heuristic'. Proceeding with 'heuristic'",
  85. value, section_name, config_name);
  86. return simple_pattern_is_potential_name(p);
  87. }
  88. void web_server_config_options(void)
  89. {
  90. web_client_timeout =
  91. (int)config_get_number(CONFIG_SECTION_WEB, "disconnect idle clients after seconds", web_client_timeout);
  92. web_client_first_request_timeout =
  93. (int)config_get_number(CONFIG_SECTION_WEB, "timeout for first request", web_client_first_request_timeout);
  94. web_client_streaming_rate_t =
  95. config_get_number(CONFIG_SECTION_WEB, "accept a streaming request every seconds", web_client_streaming_rate_t);
  96. respect_web_browser_do_not_track_policy =
  97. config_get_boolean(CONFIG_SECTION_WEB, "respect do not track policy", respect_web_browser_do_not_track_policy);
  98. web_x_frame_options = config_get(CONFIG_SECTION_WEB, "x-frame-options response header", "");
  99. if(!*web_x_frame_options)
  100. web_x_frame_options = NULL;
  101. web_allow_connections_from =
  102. simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow connections from", "localhost *"),
  103. NULL, SIMPLE_PATTERN_EXACT);
  104. web_allow_connections_dns =
  105. make_dns_decision(CONFIG_SECTION_WEB, "allow connections by dns", "heuristic", web_allow_connections_from);
  106. web_allow_dashboard_from =
  107. simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow dashboard from", "localhost *"),
  108. NULL, SIMPLE_PATTERN_EXACT);
  109. web_allow_dashboard_dns =
  110. make_dns_decision(CONFIG_SECTION_WEB, "allow dashboard by dns", "heuristic", web_allow_dashboard_from);
  111. web_allow_badges_from =
  112. simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow badges from", "*"), NULL, SIMPLE_PATTERN_EXACT);
  113. web_allow_badges_dns =
  114. make_dns_decision(CONFIG_SECTION_WEB, "allow badges by dns", "heuristic", web_allow_badges_from);
  115. web_allow_registry_from =
  116. simple_pattern_create(config_get(CONFIG_SECTION_REGISTRY, "allow from", "*"), NULL, SIMPLE_PATTERN_EXACT);
  117. web_allow_registry_dns = make_dns_decision(CONFIG_SECTION_REGISTRY, "allow by dns", "heuristic",
  118. web_allow_registry_from);
  119. web_allow_streaming_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow streaming from", "*"),
  120. NULL, SIMPLE_PATTERN_EXACT);
  121. web_allow_streaming_dns = make_dns_decision(CONFIG_SECTION_WEB, "allow streaming by dns", "heuristic",
  122. web_allow_streaming_from);
  123. // Note the default is not heuristic, the wildcards could match DNS but the intent is ip-addresses.
  124. web_allow_netdataconf_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow netdata.conf from",
  125. "localhost fd* 10.* 192.168.* 172.16.* 172.17.* 172.18.*"
  126. " 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.*"
  127. " 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.*"
  128. " 172.31.* UNKNOWN"), NULL, SIMPLE_PATTERN_EXACT);
  129. web_allow_netdataconf_dns =
  130. make_dns_decision(CONFIG_SECTION_WEB, "allow netdata.conf by dns", "no", web_allow_netdataconf_from);
  131. web_allow_mgmt_from =
  132. simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow management from", "localhost"),
  133. NULL, SIMPLE_PATTERN_EXACT);
  134. web_allow_mgmt_dns =
  135. make_dns_decision(CONFIG_SECTION_WEB, "allow management by dns","heuristic",web_allow_mgmt_from);
  136. #ifdef NETDATA_WITH_ZLIB
  137. web_enable_gzip = config_get_boolean(CONFIG_SECTION_WEB, "enable gzip compression", web_enable_gzip);
  138. char *s = config_get(CONFIG_SECTION_WEB, "gzip compression strategy", "default");
  139. if(!strcmp(s, "default"))
  140. web_gzip_strategy = Z_DEFAULT_STRATEGY;
  141. else if(!strcmp(s, "filtered"))
  142. web_gzip_strategy = Z_FILTERED;
  143. else if(!strcmp(s, "huffman only"))
  144. web_gzip_strategy = Z_HUFFMAN_ONLY;
  145. else if(!strcmp(s, "rle"))
  146. web_gzip_strategy = Z_RLE;
  147. else if(!strcmp(s, "fixed"))
  148. web_gzip_strategy = Z_FIXED;
  149. else {
  150. error("Invalid compression strategy '%s'. Valid strategies are 'default', 'filtered', 'huffman only', 'rle' and 'fixed'. Proceeding with 'default'.", s);
  151. web_gzip_strategy = Z_DEFAULT_STRATEGY;
  152. }
  153. web_gzip_level = (int)config_get_number(CONFIG_SECTION_WEB, "gzip compression level", 3);
  154. if(web_gzip_level < 1) {
  155. error("Invalid compression level %d. Valid levels are 1 (fastest) to 9 (best ratio). Proceeding with level 1 (fastest compression).", web_gzip_level);
  156. web_gzip_level = 1;
  157. }
  158. else if(web_gzip_level > 9) {
  159. error("Invalid compression level %d. Valid levels are 1 (fastest) to 9 (best ratio). Proceeding with level 9 (best compression).", web_gzip_level);
  160. web_gzip_level = 9;
  161. }
  162. #endif /* NETDATA_WITH_ZLIB */
  163. }
  164. // killpid kills pid with SIGTERM.
  165. int killpid(pid_t pid) {
  166. int ret;
  167. debug(D_EXIT, "Request to kill pid %d", pid);
  168. errno = 0;
  169. ret = kill(pid, SIGTERM);
  170. if (ret == -1) {
  171. switch(errno) {
  172. case ESRCH:
  173. // We wanted the process to exit so just let the caller handle.
  174. return ret;
  175. case EPERM:
  176. error("Cannot kill pid %d, but I do not have enough permissions.", pid);
  177. break;
  178. default:
  179. error("Cannot kill pid %d, but I received an error.", pid);
  180. break;
  181. }
  182. }
  183. return ret;
  184. }
  185. void cancel_main_threads() {
  186. error_log_limit_unlimited();
  187. int i, found = 0;
  188. usec_t max = 5 * USEC_PER_SEC, step = 100000;
  189. for (i = 0; static_threads[i].name != NULL ; i++) {
  190. if(static_threads[i].enabled == NETDATA_MAIN_THREAD_RUNNING) {
  191. info("EXIT: Stopping main thread: %s", static_threads[i].name);
  192. netdata_thread_cancel(*static_threads[i].thread);
  193. found++;
  194. }
  195. }
  196. netdata_exit = 1;
  197. while(found && max > 0) {
  198. max -= step;
  199. info("Waiting %d threads to finish...", found);
  200. sleep_usec(step);
  201. found = 0;
  202. for (i = 0; static_threads[i].name != NULL ; i++) {
  203. if (static_threads[i].enabled != NETDATA_MAIN_THREAD_EXITED)
  204. found++;
  205. }
  206. }
  207. if(found) {
  208. for (i = 0; static_threads[i].name != NULL ; i++) {
  209. if (static_threads[i].enabled != NETDATA_MAIN_THREAD_EXITED)
  210. error("Main thread %s takes too long to exit. Giving up...", static_threads[i].name);
  211. }
  212. }
  213. else
  214. info("All threads finished.");
  215. for (i = 0; static_threads[i].name != NULL ; i++)
  216. freez(static_threads[i].thread);
  217. free(static_threads);
  218. }
  219. struct option_def option_definitions[] = {
  220. // opt description arg name default value
  221. { 'c', "Configuration file to load.", "filename", CONFIG_DIR "/" CONFIG_FILENAME},
  222. { 'D', "Do not fork. Run in the foreground.", NULL, "run in the background"},
  223. { 'd', "Fork. Run in the background.", NULL, "run in the background"},
  224. { 'h', "Display this help message.", NULL, NULL},
  225. { 'P', "File to save a pid while running.", "filename", "do not save pid to a file"},
  226. { 'i', "The IP address to listen to.", "IP", "all IP addresses IPv4 and IPv6"},
  227. { 'p', "API/Web port to use.", "port", "19999"},
  228. { 's', "Prefix for /proc and /sys (for containers).", "path", "no prefix"},
  229. { 't', "The internal clock of netdata.", "seconds", "1"},
  230. { 'u', "Run as user.", "username", "netdata"},
  231. { 'v', "Print netdata version and exit.", NULL, NULL},
  232. { 'V', "Print netdata version and exit.", NULL, NULL},
  233. { 'W', "See Advanced options below.", "options", NULL},
  234. };
  235. int help(int exitcode) {
  236. FILE *stream;
  237. if(exitcode == 0)
  238. stream = stdout;
  239. else
  240. stream = stderr;
  241. int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
  242. int i;
  243. int max_len_arg = 0;
  244. // Compute maximum argument length
  245. for( i = 0; i < num_opts; i++ ) {
  246. if(option_definitions[i].arg_name) {
  247. int len_arg = (int)strlen(option_definitions[i].arg_name);
  248. if(len_arg > max_len_arg) max_len_arg = len_arg;
  249. }
  250. }
  251. if(max_len_arg > 30) max_len_arg = 30;
  252. if(max_len_arg < 20) max_len_arg = 20;
  253. fprintf(stream, "%s", "\n"
  254. " ^\n"
  255. " |.-. .-. .-. .-. . netdata \n"
  256. " | '-' '-' '-' '-' real-time performance monitoring, done right! \n"
  257. " +----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+--->\n"
  258. "\n"
  259. " Copyright (C) 2016-2020, Netdata, Inc. <info@netdata.cloud>\n"
  260. " Released under GNU General Public License v3 or later.\n"
  261. " All rights reserved.\n"
  262. "\n"
  263. " Home Page : https://netdata.cloud\n"
  264. " Source Code: https://github.com/netdata/netdata\n"
  265. " Docs : https://learn.netdata.cloud\n"
  266. " Support : https://github.com/netdata/netdata/issues\n"
  267. " License : https://github.com/netdata/netdata/blob/master/LICENSE.md\n"
  268. "\n"
  269. " Twitter : https://twitter.com/linuxnetdata\n"
  270. " Facebook : https://www.facebook.com/linuxnetdata/\n"
  271. "\n"
  272. "\n"
  273. );
  274. fprintf(stream, " SYNOPSIS: netdata [options]\n");
  275. fprintf(stream, "\n");
  276. fprintf(stream, " Options:\n\n");
  277. // Output options description.
  278. for( i = 0; i < num_opts; i++ ) {
  279. fprintf(stream, " -%c %-*s %s", option_definitions[i].val, max_len_arg, option_definitions[i].arg_name ? option_definitions[i].arg_name : "", option_definitions[i].description);
  280. if(option_definitions[i].default_value) {
  281. fprintf(stream, "\n %c %-*s Default: %s\n", ' ', max_len_arg, "", option_definitions[i].default_value);
  282. } else {
  283. fprintf(stream, "\n");
  284. }
  285. fprintf(stream, "\n");
  286. }
  287. fprintf(stream, "\n Advanced options:\n\n"
  288. " -W stacksize=N Set the stacksize (in bytes).\n\n"
  289. " -W debug_flags=N Set runtime tracing to debug.log.\n\n"
  290. " -W unittest Run internal unittests and exit.\n\n"
  291. " -W sqlite-check Check metadata database integrity and exit.\n\n"
  292. " -W sqlite-fix Check metadata database integrity, fix if needed and exit.\n\n"
  293. " -W sqlite-compact Reclaim metadata database unused space and exit.\n\n"
  294. #ifdef ENABLE_DBENGINE
  295. " -W createdataset=N Create a DB engine dataset of N seconds and exit.\n\n"
  296. " -W stresstest=A,B,C,D,E,F,G\n"
  297. " Run a DB engine stress test for A seconds,\n"
  298. " with B writers and C readers, with a ramp up\n"
  299. " time of D seconds for writers, a page cache\n"
  300. " size of E MiB, an optional disk space limit\n"
  301. " of F MiB, G libuv workers (default 16) and exit.\n\n"
  302. #endif
  303. " -W set section option value\n"
  304. " set netdata.conf option from the command line.\n\n"
  305. " -W simple-pattern pattern string\n"
  306. " Check if string matches pattern and exit.\n\n"
  307. " -W \"claim -token=TOKEN -rooms=ROOM1,ROOM2\"\n"
  308. " Claim the agent to the workspace rooms pointed to by TOKEN and ROOM*.\n\n"
  309. );
  310. fprintf(stream, "\n Signals netdata handles:\n\n"
  311. " - HUP Close and reopen log files.\n"
  312. " - USR1 Save internal DB to disk.\n"
  313. " - USR2 Reload health configuration.\n"
  314. "\n"
  315. );
  316. fflush(stream);
  317. return exitcode;
  318. }
  319. #ifdef ENABLE_HTTPS
  320. static void security_init(){
  321. char filename[FILENAME_MAX + 1];
  322. snprintfz(filename, FILENAME_MAX, "%s/ssl/key.pem",netdata_configured_user_config_dir);
  323. security_key = config_get(CONFIG_SECTION_WEB, "ssl key", filename);
  324. snprintfz(filename, FILENAME_MAX, "%s/ssl/cert.pem",netdata_configured_user_config_dir);
  325. security_cert = config_get(CONFIG_SECTION_WEB, "ssl certificate", filename);
  326. tls_version = config_get(CONFIG_SECTION_WEB, "tls version", "1.3");
  327. tls_ciphers = config_get(CONFIG_SECTION_WEB, "tls ciphers", "none");
  328. security_openssl_library();
  329. }
  330. #endif
  331. static void log_init(void) {
  332. char filename[FILENAME_MAX + 1];
  333. snprintfz(filename, FILENAME_MAX, "%s/debug.log", netdata_configured_log_dir);
  334. stdout_filename = config_get(CONFIG_SECTION_LOGS, "debug", filename);
  335. snprintfz(filename, FILENAME_MAX, "%s/error.log", netdata_configured_log_dir);
  336. stderr_filename = config_get(CONFIG_SECTION_LOGS, "error", filename);
  337. snprintfz(filename, FILENAME_MAX, "%s/access.log", netdata_configured_log_dir);
  338. stdaccess_filename = config_get(CONFIG_SECTION_LOGS, "access", filename);
  339. char deffacility[8];
  340. snprintfz(deffacility,7,"%s","daemon");
  341. facility_log = config_get(CONFIG_SECTION_LOGS, "facility", deffacility);
  342. error_log_throttle_period = config_get_number(CONFIG_SECTION_LOGS, "errors flood protection period", error_log_throttle_period);
  343. error_log_errors_per_period = (unsigned long)config_get_number(CONFIG_SECTION_LOGS, "errors to trigger flood protection", (long long int)error_log_errors_per_period);
  344. error_log_errors_per_period_backup = error_log_errors_per_period;
  345. setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get(CONFIG_SECTION_LOGS, "errors flood protection period" , ""), 1);
  346. setenv("NETDATA_ERRORS_PER_PERIOD", config_get(CONFIG_SECTION_LOGS, "errors to trigger flood protection", ""), 1);
  347. }
  348. char *initialize_lock_directory_path(char *prefix)
  349. {
  350. char filename[FILENAME_MAX + 1];
  351. snprintfz(filename, FILENAME_MAX, "%s/lock", prefix);
  352. return config_get(CONFIG_SECTION_DIRECTORIES, "lock", filename);
  353. }
  354. static void backwards_compatible_config() {
  355. // move [global] options to the [web] section
  356. config_move(CONFIG_SECTION_GLOBAL, "http port listen backlog",
  357. CONFIG_SECTION_WEB, "listen backlog");
  358. config_move(CONFIG_SECTION_GLOBAL, "bind socket to IP",
  359. CONFIG_SECTION_WEB, "bind to");
  360. config_move(CONFIG_SECTION_GLOBAL, "bind to",
  361. CONFIG_SECTION_WEB, "bind to");
  362. config_move(CONFIG_SECTION_GLOBAL, "port",
  363. CONFIG_SECTION_WEB, "default port");
  364. config_move(CONFIG_SECTION_GLOBAL, "default port",
  365. CONFIG_SECTION_WEB, "default port");
  366. config_move(CONFIG_SECTION_GLOBAL, "disconnect idle web clients after seconds",
  367. CONFIG_SECTION_WEB, "disconnect idle clients after seconds");
  368. config_move(CONFIG_SECTION_GLOBAL, "respect web browser do not track policy",
  369. CONFIG_SECTION_WEB, "respect do not track policy");
  370. config_move(CONFIG_SECTION_GLOBAL, "web x-frame-options header",
  371. CONFIG_SECTION_WEB, "x-frame-options response header");
  372. config_move(CONFIG_SECTION_GLOBAL, "enable web responses gzip compression",
  373. CONFIG_SECTION_WEB, "enable gzip compression");
  374. config_move(CONFIG_SECTION_GLOBAL, "web compression strategy",
  375. CONFIG_SECTION_WEB, "gzip compression strategy");
  376. config_move(CONFIG_SECTION_GLOBAL, "web compression level",
  377. CONFIG_SECTION_WEB, "gzip compression level");
  378. config_move(CONFIG_SECTION_GLOBAL, "config directory",
  379. CONFIG_SECTION_DIRECTORIES, "config");
  380. config_move(CONFIG_SECTION_GLOBAL, "stock config directory",
  381. CONFIG_SECTION_DIRECTORIES, "stock config");
  382. config_move(CONFIG_SECTION_GLOBAL, "log directory",
  383. CONFIG_SECTION_DIRECTORIES, "log");
  384. config_move(CONFIG_SECTION_GLOBAL, "web files directory",
  385. CONFIG_SECTION_DIRECTORIES, "web");
  386. config_move(CONFIG_SECTION_GLOBAL, "cache directory",
  387. CONFIG_SECTION_DIRECTORIES, "cache");
  388. config_move(CONFIG_SECTION_GLOBAL, "lib directory",
  389. CONFIG_SECTION_DIRECTORIES, "lib");
  390. config_move(CONFIG_SECTION_GLOBAL, "home directory",
  391. CONFIG_SECTION_DIRECTORIES, "home");
  392. config_move(CONFIG_SECTION_GLOBAL, "lock directory",
  393. CONFIG_SECTION_DIRECTORIES, "lock");
  394. config_move(CONFIG_SECTION_GLOBAL, "plugins directory",
  395. CONFIG_SECTION_DIRECTORIES, "plugins");
  396. config_move(CONFIG_SECTION_HEALTH, "health configuration directory",
  397. CONFIG_SECTION_DIRECTORIES, "health config");
  398. config_move(CONFIG_SECTION_HEALTH, "stock health configuration directory",
  399. CONFIG_SECTION_DIRECTORIES, "stock health config");
  400. config_move(CONFIG_SECTION_REGISTRY, "registry db directory",
  401. CONFIG_SECTION_DIRECTORIES, "registry");
  402. config_move(CONFIG_SECTION_GLOBAL, "debug log",
  403. CONFIG_SECTION_LOGS, "debug");
  404. config_move(CONFIG_SECTION_GLOBAL, "error log",
  405. CONFIG_SECTION_LOGS, "error");
  406. config_move(CONFIG_SECTION_GLOBAL, "access log",
  407. CONFIG_SECTION_LOGS, "access");
  408. config_move(CONFIG_SECTION_GLOBAL, "facility log",
  409. CONFIG_SECTION_LOGS, "facility");
  410. config_move(CONFIG_SECTION_GLOBAL, "errors flood protection period",
  411. CONFIG_SECTION_LOGS, "errors flood protection period");
  412. config_move(CONFIG_SECTION_GLOBAL, "errors to trigger flood protection",
  413. CONFIG_SECTION_LOGS, "errors to trigger flood protection");
  414. config_move(CONFIG_SECTION_GLOBAL, "debug flags",
  415. CONFIG_SECTION_LOGS, "debug flags");
  416. config_move(CONFIG_SECTION_GLOBAL, "TZ environment variable",
  417. CONFIG_SECTION_ENV_VARS, "TZ");
  418. config_move(CONFIG_SECTION_PLUGINS, "PATH environment variable",
  419. CONFIG_SECTION_ENV_VARS, "PATH");
  420. config_move(CONFIG_SECTION_PLUGINS, "PYTHONPATH environment variable",
  421. CONFIG_SECTION_ENV_VARS, "PYTHONPATH");
  422. config_move(CONFIG_SECTION_STATSD, "enabled",
  423. CONFIG_SECTION_PLUGINS, "statsd");
  424. }
  425. static void get_netdata_configured_variables() {
  426. backwards_compatible_config();
  427. // ------------------------------------------------------------------------
  428. // get the hostname
  429. char buf[HOSTNAME_MAX + 1];
  430. if(gethostname(buf, HOSTNAME_MAX) == -1){
  431. error("Cannot get machine hostname.");
  432. }
  433. netdata_configured_hostname = config_get(CONFIG_SECTION_GLOBAL, "hostname", buf);
  434. debug(D_OPTIONS, "hostname set to '%s'", netdata_configured_hostname);
  435. // ------------------------------------------------------------------------
  436. // get default database size
  437. default_rrd_history_entries = (int) config_get_number(CONFIG_SECTION_GLOBAL, "history", align_entries_to_pagesize(default_rrd_memory_mode, RRD_DEFAULT_HISTORY_ENTRIES));
  438. long h = align_entries_to_pagesize(default_rrd_memory_mode, default_rrd_history_entries);
  439. if(h != default_rrd_history_entries) {
  440. config_set_number(CONFIG_SECTION_GLOBAL, "history", h);
  441. default_rrd_history_entries = (int)h;
  442. }
  443. if(default_rrd_history_entries < 5 || default_rrd_history_entries > RRD_HISTORY_ENTRIES_MAX) {
  444. error("Invalid history entries %d given. Defaulting to %d.", default_rrd_history_entries, RRD_DEFAULT_HISTORY_ENTRIES);
  445. default_rrd_history_entries = RRD_DEFAULT_HISTORY_ENTRIES;
  446. }
  447. // ------------------------------------------------------------------------
  448. // get default database update frequency
  449. default_rrd_update_every = (int) config_get_number(CONFIG_SECTION_GLOBAL, "update every", UPDATE_EVERY);
  450. if(default_rrd_update_every < 1 || default_rrd_update_every > 600) {
  451. error("Invalid data collection frequency (update every) %d given. Defaulting to %d.", default_rrd_update_every, UPDATE_EVERY_MAX);
  452. default_rrd_update_every = UPDATE_EVERY;
  453. }
  454. // ------------------------------------------------------------------------
  455. // get system paths
  456. netdata_configured_user_config_dir = config_get(CONFIG_SECTION_DIRECTORIES, "config", netdata_configured_user_config_dir);
  457. netdata_configured_stock_config_dir = config_get(CONFIG_SECTION_DIRECTORIES, "stock config", netdata_configured_stock_config_dir);
  458. netdata_configured_log_dir = config_get(CONFIG_SECTION_DIRECTORIES, "log", netdata_configured_log_dir);
  459. netdata_configured_web_dir = config_get(CONFIG_SECTION_DIRECTORIES, "web", netdata_configured_web_dir);
  460. netdata_configured_cache_dir = config_get(CONFIG_SECTION_DIRECTORIES, "cache", netdata_configured_cache_dir);
  461. netdata_configured_varlib_dir = config_get(CONFIG_SECTION_DIRECTORIES, "lib", netdata_configured_varlib_dir);
  462. char *env_home=getenv("HOME");
  463. netdata_configured_home_dir = config_get(CONFIG_SECTION_DIRECTORIES, "home", env_home?env_home:netdata_configured_home_dir);
  464. netdata_configured_lock_dir = initialize_lock_directory_path(netdata_configured_varlib_dir);
  465. {
  466. pluginsd_initialize_plugin_directories();
  467. netdata_configured_primary_plugins_dir = plugin_directories[PLUGINSD_STOCK_PLUGINS_DIRECTORY_PATH];
  468. }
  469. // ------------------------------------------------------------------------
  470. // get default memory mode for the database
  471. default_rrd_memory_mode = rrd_memory_mode_id(config_get(CONFIG_SECTION_GLOBAL, "memory mode", rrd_memory_mode_name(default_rrd_memory_mode)));
  472. #ifdef ENABLE_DBENGINE
  473. // ------------------------------------------------------------------------
  474. // get default Database Engine page cache size in MiB
  475. default_rrdeng_page_cache_mb = (int) config_get_number(CONFIG_SECTION_GLOBAL, "page cache size", default_rrdeng_page_cache_mb);
  476. if(default_rrdeng_page_cache_mb < RRDENG_MIN_PAGE_CACHE_SIZE_MB) {
  477. error("Invalid page cache size %d given. Defaulting to %d.", default_rrdeng_page_cache_mb, RRDENG_MIN_PAGE_CACHE_SIZE_MB);
  478. default_rrdeng_page_cache_mb = RRDENG_MIN_PAGE_CACHE_SIZE_MB;
  479. }
  480. // ------------------------------------------------------------------------
  481. // get default Database Engine disk space quota in MiB
  482. default_rrdeng_disk_quota_mb = (int) config_get_number(CONFIG_SECTION_GLOBAL, "dbengine disk space", default_rrdeng_disk_quota_mb);
  483. if(default_rrdeng_disk_quota_mb < RRDENG_MIN_DISK_SPACE_MB) {
  484. error("Invalid dbengine disk space %d given. Defaulting to %d.", default_rrdeng_disk_quota_mb, RRDENG_MIN_DISK_SPACE_MB);
  485. default_rrdeng_disk_quota_mb = RRDENG_MIN_DISK_SPACE_MB;
  486. }
  487. default_multidb_disk_quota_mb = (int) config_get_number(CONFIG_SECTION_GLOBAL, "dbengine multihost disk space", compute_multidb_diskspace());
  488. if(default_multidb_disk_quota_mb < RRDENG_MIN_DISK_SPACE_MB) {
  489. error("Invalid multidb disk space %d given. Defaulting to %d.", default_multidb_disk_quota_mb, default_rrdeng_disk_quota_mb);
  490. default_multidb_disk_quota_mb = default_rrdeng_disk_quota_mb;
  491. }
  492. #else
  493. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
  494. error_report("RRD_MEMORY_MODE_DBENGINE is not supported in this platform. The agent will use memory mode ram instead.");
  495. default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
  496. }
  497. #endif
  498. // ------------------------------------------------------------------------
  499. netdata_configured_host_prefix = config_get(CONFIG_SECTION_GLOBAL, "host access prefix", "");
  500. verify_netdata_host_prefix();
  501. // --------------------------------------------------------------------
  502. // get KSM settings
  503. #ifdef MADV_MERGEABLE
  504. enable_ksm = config_get_boolean(CONFIG_SECTION_GLOBAL, "memory deduplication (ksm)", enable_ksm);
  505. #endif
  506. // --------------------------------------------------------------------
  507. // metric correlations
  508. enable_metric_correlations = config_get_boolean(CONFIG_SECTION_GLOBAL, "enable metric correlations", enable_metric_correlations);
  509. // --------------------------------------------------------------------
  510. // get various system parameters
  511. get_system_HZ();
  512. get_system_cpus();
  513. get_system_pid_max();
  514. }
  515. int load_netdata_conf(char *filename, char overwrite_used) {
  516. errno = 0;
  517. int ret = 0;
  518. if(filename && *filename) {
  519. ret = config_load(filename, overwrite_used, NULL);
  520. if(!ret)
  521. error("CONFIG: cannot load config file '%s'.", filename);
  522. }
  523. else {
  524. filename = strdupz_path_subpath(netdata_configured_user_config_dir, "netdata.conf");
  525. ret = config_load(filename, overwrite_used, NULL);
  526. if(!ret) {
  527. info("CONFIG: cannot load user config '%s'. Will try the stock version.", filename);
  528. freez(filename);
  529. filename = strdupz_path_subpath(netdata_configured_stock_config_dir, "netdata.conf");
  530. ret = config_load(filename, overwrite_used, NULL);
  531. if(!ret)
  532. info("CONFIG: cannot load stock config '%s'. Running with internal defaults.", filename);
  533. }
  534. freez(filename);
  535. }
  536. return ret;
  537. }
  538. // coverity[ +tainted_string_sanitize_content : arg-0 ]
  539. static inline void coverity_remove_taint(char *s)
  540. {
  541. (void)s;
  542. }
  543. int get_system_info(struct rrdhost_system_info *system_info) {
  544. char *script;
  545. script = mallocz(sizeof(char) * (strlen(netdata_configured_primary_plugins_dir) + strlen("system-info.sh") + 2));
  546. sprintf(script, "%s/%s", netdata_configured_primary_plugins_dir, "system-info.sh");
  547. if (unlikely(access(script, R_OK) != 0)) {
  548. info("System info script %s not found.",script);
  549. freez(script);
  550. return 1;
  551. }
  552. pid_t command_pid;
  553. info("Executing %s", script);
  554. FILE *fp = mypopen(script, &command_pid);
  555. if(fp) {
  556. char line[200 + 1];
  557. // Removed the double strlens, if the Coverity tainted string warning reappears I'll revert.
  558. // One time init code, but I'm curious about the warning...
  559. while (fgets(line, 200, fp) != NULL) {
  560. char *value=line;
  561. while (*value && *value != '=') value++;
  562. if (*value=='=') {
  563. *value='\0';
  564. value++;
  565. char *end = value;
  566. while (*end && *end != '\n') end++;
  567. *end = '\0'; // Overwrite newline if present
  568. coverity_remove_taint(line); // I/O is controlled result of system_info.sh - not tainted
  569. coverity_remove_taint(value);
  570. if(unlikely(rrdhost_set_system_info_variable(system_info, line, value))) {
  571. info("Unexpected environment variable %s=%s", line, value);
  572. }
  573. else {
  574. info("%s=%s", line, value);
  575. setenv(line, value, 1);
  576. }
  577. }
  578. }
  579. mypclose(fp, command_pid);
  580. }
  581. freez(script);
  582. return 0;
  583. }
  584. void set_silencers_filename() {
  585. char filename[FILENAME_MAX + 1];
  586. snprintfz(filename, FILENAME_MAX, "%s/health.silencers.json", netdata_configured_varlib_dir);
  587. silencers_filename = config_get(CONFIG_SECTION_HEALTH, "silencers file", filename);
  588. }
  589. /* Any config setting that can be accessed without a default value i.e. configget(...,...,NULL) *MUST*
  590. be set in this procedure to be called in all the relevant code paths.
  591. */
  592. void post_conf_load(char **user)
  593. {
  594. // --------------------------------------------------------------------
  595. // get the user we should run
  596. // IMPORTANT: this is required before web_files_uid()
  597. if(getuid() == 0) {
  598. *user = config_get(CONFIG_SECTION_GLOBAL, "run as user", NETDATA_USER);
  599. }
  600. else {
  601. struct passwd *passwd = getpwuid(getuid());
  602. *user = config_get(CONFIG_SECTION_GLOBAL, "run as user", (passwd && passwd->pw_name)?passwd->pw_name:"");
  603. }
  604. // --------------------------------------------------------------------
  605. // Check if the cloud is enabled
  606. #if defined( DISABLE_CLOUD ) || !defined( ENABLE_ACLK )
  607. netdata_cloud_setting = 0;
  608. #else
  609. netdata_cloud_setting = appconfig_get_boolean(&cloud_config, CONFIG_SECTION_GLOBAL, "enabled", 1);
  610. #endif
  611. // This must be set before any point in the code that accesses it. Do not move it from this function.
  612. appconfig_get(&cloud_config, CONFIG_SECTION_GLOBAL, "cloud base url", DEFAULT_CLOUD_BASE_URL);
  613. }
  614. int main(int argc, char **argv) {
  615. int i;
  616. int config_loaded = 0;
  617. int dont_fork = 0;
  618. bool close_open_fds = true;
  619. size_t default_stacksize;
  620. char *user = NULL;
  621. static_threads = static_threads_get();
  622. netdata_ready=0;
  623. // set the name for logging
  624. program_name = "netdata";
  625. if (argc > 1 && strcmp(argv[1], SPAWN_SERVER_COMMAND_LINE_ARGUMENT) == 0) {
  626. // don't run netdata, this is the spawn server
  627. spawn_server();
  628. exit(0);
  629. }
  630. // parse options
  631. {
  632. int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
  633. char optstring[(num_opts * 2) + 1];
  634. int string_i = 0;
  635. for( i = 0; i < num_opts; i++ ) {
  636. optstring[string_i] = option_definitions[i].val;
  637. string_i++;
  638. if(option_definitions[i].arg_name) {
  639. optstring[string_i] = ':';
  640. string_i++;
  641. }
  642. }
  643. // terminate optstring
  644. optstring[string_i] ='\0';
  645. optstring[(num_opts *2)] ='\0';
  646. int opt;
  647. while( (opt = getopt(argc, argv, optstring)) != -1 ) {
  648. switch(opt) {
  649. case 'c':
  650. if(load_netdata_conf(optarg, 1) != 1) {
  651. error("Cannot load configuration file %s.", optarg);
  652. return 1;
  653. }
  654. else {
  655. debug(D_OPTIONS, "Configuration loaded from %s.", optarg);
  656. post_conf_load(&user);
  657. load_cloud_conf(1);
  658. config_loaded = 1;
  659. }
  660. break;
  661. case 'D':
  662. dont_fork = 1;
  663. break;
  664. case 'd':
  665. dont_fork = 0;
  666. break;
  667. case 'h':
  668. return help(0);
  669. case 'i':
  670. config_set(CONFIG_SECTION_WEB, "bind to", optarg);
  671. break;
  672. case 'P':
  673. strncpy(pidfile, optarg, FILENAME_MAX);
  674. pidfile[FILENAME_MAX] = '\0';
  675. break;
  676. case 'p':
  677. config_set(CONFIG_SECTION_GLOBAL, "default port", optarg);
  678. break;
  679. case 's':
  680. config_set(CONFIG_SECTION_GLOBAL, "host access prefix", optarg);
  681. break;
  682. case 't':
  683. config_set(CONFIG_SECTION_GLOBAL, "update every", optarg);
  684. break;
  685. case 'u':
  686. config_set(CONFIG_SECTION_GLOBAL, "run as user", optarg);
  687. break;
  688. case 'v':
  689. case 'V':
  690. printf("%s %s\n", program_name, program_version);
  691. return 0;
  692. case 'W':
  693. {
  694. char* stacksize_string = "stacksize=";
  695. char* debug_flags_string = "debug_flags=";
  696. char* claim_string = "claim";
  697. #ifdef ENABLE_DBENGINE
  698. char* createdataset_string = "createdataset=";
  699. char* stresstest_string = "stresstest=";
  700. #endif
  701. if(strcmp(optarg, "sqlite-check") == 0) {
  702. sql_init_database(DB_CHECK_INTEGRITY, 0);
  703. return 0;
  704. }
  705. if(strcmp(optarg, "sqlite-fix") == 0) {
  706. sql_init_database(DB_CHECK_FIX_DB, 0);
  707. return 0;
  708. }
  709. if(strcmp(optarg, "sqlite-compact") == 0) {
  710. sql_init_database(DB_CHECK_RECLAIM_SPACE, 0);
  711. return 0;
  712. }
  713. if(strcmp(optarg, "unittest") == 0) {
  714. if (unit_test_static_threads())
  715. return 1;
  716. if (unit_test_buffer())
  717. return 1;
  718. if (unit_test_str2ld())
  719. return 1;
  720. // No call to load the config file on this code-path
  721. post_conf_load(&user);
  722. get_netdata_configured_variables();
  723. default_rrd_update_every = 1;
  724. default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
  725. default_health_enabled = 0;
  726. registry_init();
  727. if(rrd_init("unittest", NULL)) {
  728. fprintf(stderr, "rrd_init failed for unittest\n");
  729. return 1;
  730. }
  731. default_rrdpush_enabled = 0;
  732. if(run_all_mockup_tests()) return 1;
  733. if(unit_test_storage()) return 1;
  734. #ifdef ENABLE_DBENGINE
  735. if(test_dbengine()) return 1;
  736. #endif
  737. if(test_sqlite()) return 1;
  738. fprintf(stderr, "\n\nALL TESTS PASSED\n\n");
  739. return 0;
  740. }
  741. #ifdef ENABLE_ML_TESTS
  742. else if(strcmp(optarg, "mltest") == 0) {
  743. return test_ml(argc, argv);
  744. }
  745. #endif
  746. #ifdef ENABLE_DBENGINE
  747. else if(strcmp(optarg, "dicttest") == 0) {
  748. return dictionary_unittest(10000);
  749. }
  750. else if(strncmp(optarg, createdataset_string, strlen(createdataset_string)) == 0) {
  751. optarg += strlen(createdataset_string);
  752. unsigned history_seconds = strtoul(optarg, NULL, 0);
  753. generate_dbengine_dataset(history_seconds);
  754. return 0;
  755. }
  756. else if(strncmp(optarg, stresstest_string, strlen(stresstest_string)) == 0) {
  757. char *endptr;
  758. unsigned test_duration_sec = 0, dset_charts = 0, query_threads = 0, ramp_up_seconds = 0,
  759. page_cache_mb = 0, disk_space_mb = 0, workers = 16;
  760. optarg += strlen(stresstest_string);
  761. test_duration_sec = (unsigned)strtoul(optarg, &endptr, 0);
  762. if (',' == *endptr)
  763. dset_charts = (unsigned)strtoul(endptr + 1, &endptr, 0);
  764. if (',' == *endptr)
  765. query_threads = (unsigned)strtoul(endptr + 1, &endptr, 0);
  766. if (',' == *endptr)
  767. ramp_up_seconds = (unsigned)strtoul(endptr + 1, &endptr, 0);
  768. if (',' == *endptr)
  769. page_cache_mb = (unsigned)strtoul(endptr + 1, &endptr, 0);
  770. if (',' == *endptr)
  771. disk_space_mb = (unsigned)strtoul(endptr + 1, &endptr, 0);
  772. if (',' == *endptr)
  773. workers = (unsigned)strtoul(endptr + 1, &endptr, 0);
  774. if (workers > 1024)
  775. workers = 1024;
  776. char workers_str[16];
  777. snprintf(workers_str, 15, "%u", workers);
  778. setenv("UV_THREADPOOL_SIZE", workers_str, 1);
  779. dbengine_stress_test(test_duration_sec, dset_charts, query_threads, ramp_up_seconds,
  780. page_cache_mb, disk_space_mb);
  781. return 0;
  782. }
  783. #endif
  784. else if(strcmp(optarg, "simple-pattern") == 0) {
  785. if(optind + 2 > argc) {
  786. fprintf(stderr, "%s", "\nUSAGE: -W simple-pattern 'pattern' 'string'\n\n"
  787. " Checks if 'pattern' matches the given 'string'.\n"
  788. " - 'pattern' can be one or more space separated words.\n"
  789. " - each 'word' can contain one or more asterisks.\n"
  790. " - words starting with '!' give negative matches.\n"
  791. " - words are processed left to right\n"
  792. "\n"
  793. "Examples:\n"
  794. "\n"
  795. " > match all veth interfaces, except veth0:\n"
  796. "\n"
  797. " -W simple-pattern '!veth0 veth*' 'veth12'\n"
  798. "\n"
  799. "\n"
  800. " > match all *.ext files directly in /path/:\n"
  801. " (this will not match *.ext files in a subdir of /path/)\n"
  802. "\n"
  803. " -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n"
  804. "\n"
  805. );
  806. return 1;
  807. }
  808. const char *haystack = argv[optind];
  809. const char *needle = argv[optind + 1];
  810. size_t len = strlen(needle) + 1;
  811. char wildcarded[len];
  812. SIMPLE_PATTERN *p = simple_pattern_create(haystack, NULL, SIMPLE_PATTERN_EXACT);
  813. int ret = simple_pattern_matches_extract(p, needle, wildcarded, len);
  814. simple_pattern_free(p);
  815. if(ret) {
  816. fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s', wildcarded '%s'\n", haystack, needle, wildcarded);
  817. return 0;
  818. }
  819. else {
  820. fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s', wildcarded '%s'\n", haystack, needle, wildcarded);
  821. return 1;
  822. }
  823. }
  824. else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) {
  825. optarg += strlen(stacksize_string);
  826. config_set(CONFIG_SECTION_GLOBAL, "pthread stack size", optarg);
  827. }
  828. else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) {
  829. optarg += strlen(debug_flags_string);
  830. config_set(CONFIG_SECTION_LOGS, "debug flags", optarg);
  831. debug_flags = strtoull(optarg, NULL, 0);
  832. }
  833. else if(strcmp(optarg, "set") == 0) {
  834. if(optind + 3 > argc) {
  835. fprintf(stderr, "%s", "\nUSAGE: -W set 'section' 'key' 'value'\n\n"
  836. " Overwrites settings of netdata.conf.\n"
  837. "\n"
  838. " These options interact with: -c netdata.conf\n"
  839. " If -c netdata.conf is given on the command line,\n"
  840. " before -W set... the user may overwrite command\n"
  841. " line parameters at netdata.conf\n"
  842. " If -c netdata.conf is given after (or missing)\n"
  843. " -W set... the user cannot overwrite the command line\n"
  844. " parameters."
  845. "\n"
  846. );
  847. return 1;
  848. }
  849. const char *section = argv[optind];
  850. const char *key = argv[optind + 1];
  851. const char *value = argv[optind + 2];
  852. optind += 3;
  853. // set this one as the default
  854. // only if it is not already set in the config file
  855. // so the caller can use -c netdata.conf before or
  856. // after this parameter to prevent or allow overwriting
  857. // variables at netdata.conf
  858. config_set_default(section, key, value);
  859. // fprintf(stderr, "SET section '%s', key '%s', value '%s'\n", section, key, value);
  860. }
  861. else if(strcmp(optarg, "set2") == 0) {
  862. if(optind + 4 > argc) {
  863. fprintf(stderr, "%s", "\nUSAGE: -W set 'conf_file' 'section' 'key' 'value'\n\n"
  864. " Overwrites settings of netdata.conf or cloud.conf\n"
  865. "\n"
  866. " These options interact with: -c netdata.conf\n"
  867. " If -c netdata.conf is given on the command line,\n"
  868. " before -W set... the user may overwrite command\n"
  869. " line parameters at netdata.conf\n"
  870. " If -c netdata.conf is given after (or missing)\n"
  871. " -W set... the user cannot overwrite the command line\n"
  872. " parameters."
  873. " conf_file can be \"cloud\" or \"netdata\".\n"
  874. "\n"
  875. );
  876. return 1;
  877. }
  878. const char *conf_file = argv[optind]; /* "cloud" is cloud.conf, otherwise netdata.conf */
  879. struct config *tmp_config = strcmp(conf_file, "cloud") ? &netdata_config : &cloud_config;
  880. const char *section = argv[optind + 1];
  881. const char *key = argv[optind + 2];
  882. const char *value = argv[optind + 3];
  883. optind += 4;
  884. // set this one as the default
  885. // only if it is not already set in the config file
  886. // so the caller can use -c netdata.conf before or
  887. // after this parameter to prevent or allow overwriting
  888. // variables at netdata.conf
  889. appconfig_set_default(tmp_config, section, key, value);
  890. // fprintf(stderr, "SET section '%s', key '%s', value '%s'\n", section, key, value);
  891. }
  892. else if(strcmp(optarg, "get") == 0) {
  893. if(optind + 3 > argc) {
  894. fprintf(stderr, "%s", "\nUSAGE: -W get 'section' 'key' 'value'\n\n"
  895. " Prints settings of netdata.conf.\n"
  896. "\n"
  897. " These options interact with: -c netdata.conf\n"
  898. " -c netdata.conf has to be given before -W get.\n"
  899. "\n"
  900. );
  901. return 1;
  902. }
  903. if(!config_loaded) {
  904. fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n");
  905. load_netdata_conf(NULL, 0);
  906. post_conf_load(&user);
  907. }
  908. get_netdata_configured_variables();
  909. const char *section = argv[optind];
  910. const char *key = argv[optind + 1];
  911. const char *def = argv[optind + 2];
  912. const char *value = config_get(section, key, def);
  913. printf("%s\n", value);
  914. return 0;
  915. }
  916. else if(strcmp(optarg, "get2") == 0) {
  917. if(optind + 4 > argc) {
  918. fprintf(stderr, "%s", "\nUSAGE: -W get2 'conf_file' 'section' 'key' 'value'\n\n"
  919. " Prints settings of netdata.conf or cloud.conf\n"
  920. "\n"
  921. " These options interact with: -c netdata.conf\n"
  922. " -c netdata.conf has to be given before -W get2.\n"
  923. " conf_file can be \"cloud\" or \"netdata\".\n"
  924. "\n"
  925. );
  926. return 1;
  927. }
  928. if(!config_loaded) {
  929. fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n");
  930. load_netdata_conf(NULL, 0);
  931. post_conf_load(&user);
  932. load_cloud_conf(1);
  933. }
  934. get_netdata_configured_variables();
  935. const char *conf_file = argv[optind]; /* "cloud" is cloud.conf, otherwise netdata.conf */
  936. struct config *tmp_config = strcmp(conf_file, "cloud") ? &netdata_config : &cloud_config;
  937. const char *section = argv[optind + 1];
  938. const char *key = argv[optind + 2];
  939. const char *def = argv[optind + 3];
  940. const char *value = appconfig_get(tmp_config, section, key, def);
  941. printf("%s\n", value);
  942. return 0;
  943. }
  944. else if(strncmp(optarg, claim_string, strlen(claim_string)) == 0) {
  945. /* will trigger a claiming attempt when the agent is initialized */
  946. claiming_pending_arguments = optarg + strlen(claim_string);
  947. }
  948. else if(strcmp(optarg, "buildinfo") == 0) {
  949. printf("Version: %s %s\n", program_name, program_version);
  950. print_build_info();
  951. return 0;
  952. }
  953. else if(strcmp(optarg, "buildinfojson") == 0) {
  954. print_build_info_json();
  955. return 0;
  956. }
  957. else if(strcmp(optarg, "keepopenfds") == 0) {
  958. // Internal dev option to skip closing inherited
  959. // open FDs. Useful, when we want to run the agent
  960. // under profiling tools that open/maintain their
  961. // own FDs.
  962. close_open_fds = false;
  963. } else {
  964. fprintf(stderr, "Unknown -W parameter '%s'\n", optarg);
  965. return help(1);
  966. }
  967. }
  968. break;
  969. default: /* ? */
  970. fprintf(stderr, "Unknown parameter '%c'\n", opt);
  971. return help(1);
  972. }
  973. }
  974. }
  975. #ifdef _SC_OPEN_MAX
  976. if (close_open_fds == true) {
  977. // close all open file descriptors, except the standard ones
  978. // the caller may have left open files (lxc-attach has this issue)
  979. for(int fd = (int) (sysconf(_SC_OPEN_MAX) - 1); fd > 2; fd--)
  980. if(fd_is_valid(fd))
  981. close(fd);
  982. }
  983. #endif
  984. if(!config_loaded)
  985. {
  986. load_netdata_conf(NULL, 0);
  987. post_conf_load(&user);
  988. load_cloud_conf(0);
  989. }
  990. // ------------------------------------------------------------------------
  991. // initialize netdata
  992. {
  993. char *pmax = config_get(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for plugins", "1");
  994. if(pmax && *pmax)
  995. setenv("MALLOC_ARENA_MAX", pmax, 1);
  996. #if defined(HAVE_C_MALLOPT)
  997. i = (int)config_get_number(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for netdata", 1);
  998. if(i > 0)
  999. mallopt(M_ARENA_MAX, 1);
  1000. #endif
  1001. // initialize the system clocks
  1002. clocks_init();
  1003. // prepare configuration environment variables for the plugins
  1004. setenv("UV_THREADPOOL_SIZE", config_get(CONFIG_SECTION_GLOBAL, "libuv worker threads", "16"), 1);
  1005. get_netdata_configured_variables();
  1006. set_global_environment();
  1007. // work while we are cd into config_dir
  1008. // to allow the plugins refer to their config
  1009. // files using relative filenames
  1010. if(chdir(netdata_configured_user_config_dir) == -1)
  1011. fatal("Cannot cd to '%s'", netdata_configured_user_config_dir);
  1012. // Get execution path before switching user to avoid permission issues
  1013. get_netdata_execution_path();
  1014. }
  1015. {
  1016. // --------------------------------------------------------------------
  1017. // get the debugging flags from the configuration file
  1018. char *flags = config_get(CONFIG_SECTION_LOGS, "debug flags", "0x0000000000000000");
  1019. setenv("NETDATA_DEBUG_FLAGS", flags, 1);
  1020. debug_flags = strtoull(flags, NULL, 0);
  1021. debug(D_OPTIONS, "Debug flags set to '0x%" PRIX64 "'.", debug_flags);
  1022. if(debug_flags != 0) {
  1023. struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
  1024. if(setrlimit(RLIMIT_CORE, &rl) != 0)
  1025. error("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
  1026. #ifdef HAVE_SYS_PRCTL_H
  1027. prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
  1028. #endif
  1029. }
  1030. // --------------------------------------------------------------------
  1031. // get log filenames and settings
  1032. log_init();
  1033. error_log_limit_unlimited();
  1034. // initialize the log files
  1035. open_all_log_files();
  1036. get_system_timezone();
  1037. // --------------------------------------------------------------------
  1038. // get the certificate and start security
  1039. #ifdef ENABLE_HTTPS
  1040. security_init();
  1041. #endif
  1042. // --------------------------------------------------------------------
  1043. // This is the safest place to start the SILENCERS structure
  1044. set_silencers_filename();
  1045. health_initialize_global_silencers();
  1046. // --------------------------------------------------------------------
  1047. // Initialize ML configuration
  1048. ml_init();
  1049. // --------------------------------------------------------------------
  1050. // setup process signals
  1051. // block signals while initializing threads.
  1052. // this causes the threads to block signals.
  1053. signals_block();
  1054. // setup the signals we want to use
  1055. signals_init();
  1056. // setup threads configs
  1057. default_stacksize = netdata_threads_init();
  1058. // --------------------------------------------------------------------
  1059. // check which threads are enabled and initialize them
  1060. for (i = 0; static_threads[i].name != NULL ; i++) {
  1061. struct netdata_static_thread *st = &static_threads[i];
  1062. if(st->config_name)
  1063. st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled);
  1064. if(st->enabled && st->init_routine)
  1065. st->init_routine();
  1066. }
  1067. // --------------------------------------------------------------------
  1068. // create the listening sockets
  1069. web_client_api_v1_init();
  1070. web_server_threading_selection();
  1071. if(web_server_mode != WEB_SERVER_MODE_NONE)
  1072. api_listen_sockets_setup();
  1073. }
  1074. #ifdef NETDATA_INTERNAL_CHECKS
  1075. if(debug_flags != 0) {
  1076. struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
  1077. if(setrlimit(RLIMIT_CORE, &rl) != 0)
  1078. error("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
  1079. #ifdef HAVE_SYS_PRCTL_H
  1080. prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
  1081. #endif
  1082. }
  1083. #endif /* NETDATA_INTERNAL_CHECKS */
  1084. // get the max file limit
  1085. if(getrlimit(RLIMIT_NOFILE, &rlimit_nofile) != 0)
  1086. error("getrlimit(RLIMIT_NOFILE) failed");
  1087. else
  1088. info("resources control: allowed file descriptors: soft = %zu, max = %zu", (size_t)rlimit_nofile.rlim_cur, (size_t)rlimit_nofile.rlim_max);
  1089. // fork, switch user, create pid file, set process priority
  1090. if(become_daemon(dont_fork, user) == -1)
  1091. fatal("Cannot daemonize myself.");
  1092. info("netdata started on pid %d.", getpid());
  1093. netdata_threads_init_after_fork((size_t)config_get_number(CONFIG_SECTION_GLOBAL, "pthread stack size", (long)default_stacksize));
  1094. // initialize internal registry
  1095. registry_init();
  1096. // fork the spawn server
  1097. spawn_init();
  1098. /*
  1099. * Libuv uv_spawn() uses SIGCHLD internally:
  1100. * https://github.com/libuv/libuv/blob/cc51217a317e96510fbb284721d5e6bc2af31e33/src/unix/process.c#L485
  1101. * and inadvertently replaces the netdata signal handler which was setup during initialization.
  1102. * Thusly, we must explicitly restore the signal handler for SIGCHLD.
  1103. * Warning: extreme care is needed when mixing and matching POSIX and libuv.
  1104. */
  1105. signals_restore_SIGCHLD();
  1106. // ------------------------------------------------------------------------
  1107. // initialize rrd, registry, health, rrdpush, etc.
  1108. netdata_anonymous_statistics_enabled=-1;
  1109. struct rrdhost_system_info *system_info = callocz(1, sizeof(struct rrdhost_system_info));
  1110. get_system_info(system_info);
  1111. system_info->hops = 0;
  1112. get_install_type(&system_info->install_type, &system_info->prebuilt_arch, &system_info->prebuilt_dist);
  1113. if(rrd_init(netdata_configured_hostname, system_info))
  1114. fatal("Cannot initialize localhost instance with name '%s'.", netdata_configured_hostname);
  1115. char agent_crash_file[FILENAME_MAX + 1];
  1116. char agent_incomplete_shutdown_file[FILENAME_MAX + 1];
  1117. snprintfz(agent_incomplete_shutdown_file, FILENAME_MAX, "%s/.agent_incomplete_shutdown", netdata_configured_varlib_dir);
  1118. int incomplete_shutdown_detected = (unlink(agent_incomplete_shutdown_file) == 0);
  1119. snprintfz(agent_crash_file, FILENAME_MAX, "%s/.agent_crash", netdata_configured_varlib_dir);
  1120. int crash_detected = (unlink(agent_crash_file) == 0);
  1121. int fd = open(agent_crash_file, O_WRONLY | O_CREAT | O_TRUNC, 444);
  1122. if (fd >= 0)
  1123. close(fd);
  1124. // ------------------------------------------------------------------------
  1125. // Claim netdata agent to a cloud endpoint
  1126. if (claiming_pending_arguments)
  1127. claim_agent(claiming_pending_arguments);
  1128. load_claiming_state();
  1129. // ------------------------------------------------------------------------
  1130. // enable log flood protection
  1131. error_log_limit_reset();
  1132. // Load host labels
  1133. reload_host_labels();
  1134. // ------------------------------------------------------------------------
  1135. // spawn the threads
  1136. web_server_config_options();
  1137. netdata_zero_metrics_enabled = config_get_boolean_ondemand(CONFIG_SECTION_GLOBAL, "enable zero metrics", CONFIG_BOOLEAN_NO);
  1138. set_late_global_environment();
  1139. for (i = 0; static_threads[i].name != NULL ; i++) {
  1140. struct netdata_static_thread *st = &static_threads[i];
  1141. if(st->enabled) {
  1142. st->thread = mallocz(sizeof(netdata_thread_t));
  1143. debug(D_SYSTEM, "Starting thread %s.", st->name);
  1144. netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, st);
  1145. }
  1146. else debug(D_SYSTEM, "Not starting thread %s.", st->name);
  1147. }
  1148. // ------------------------------------------------------------------------
  1149. // Initialize netdata agent command serving from cli and signals
  1150. commands_init();
  1151. info("netdata initialization completed. Enjoy real-time performance monitoring!");
  1152. netdata_ready = 1;
  1153. send_statistics("START", "-", "-");
  1154. if (crash_detected)
  1155. send_statistics("CRASH", "-", "-");
  1156. if (incomplete_shutdown_detected)
  1157. send_statistics("INCOMPLETE_SHUTDOWN", "-", "-");
  1158. //check if ANALYTICS needs to start
  1159. if (netdata_anonymous_statistics_enabled == 1) {
  1160. for (i = 0; static_threads[i].name != NULL; i++) {
  1161. if (!strncmp(static_threads[i].name, "ANALYTICS", 9)) {
  1162. struct netdata_static_thread *st = &static_threads[i];
  1163. st->thread = mallocz(sizeof(netdata_thread_t));
  1164. st->enabled = 1;
  1165. debug(D_SYSTEM, "Starting thread %s.", st->name);
  1166. netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, st);
  1167. }
  1168. }
  1169. }
  1170. // ------------------------------------------------------------------------
  1171. // Report ACLK build failure
  1172. #ifndef ENABLE_ACLK
  1173. error("This agent doesn't have ACLK.");
  1174. char filename[FILENAME_MAX + 1];
  1175. snprintfz(filename, FILENAME_MAX, "%s/.aclk_report_sent", netdata_configured_varlib_dir);
  1176. if (netdata_anonymous_statistics_enabled > 0 && access(filename, F_OK)) { // -1 -> not initialized
  1177. send_statistics("ACLK_DISABLED", "-", "-");
  1178. int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 444);
  1179. if (fd == -1)
  1180. error("Cannot create file '%s'. Please fix this.", filename);
  1181. else
  1182. close(fd);
  1183. }
  1184. #endif
  1185. // ------------------------------------------------------------------------
  1186. // unblock signals
  1187. signals_unblock();
  1188. // ------------------------------------------------------------------------
  1189. // Handle signals
  1190. signals_handle();
  1191. // should never reach this point
  1192. // but we need it for rpmlint #2752
  1193. return 1;
  1194. }