master
c 1,280 lines 56.9 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "common.h"
4 #include "buildinfo.h"
5 #include "daemon-shutdown-watcher.h"
6 #include "status-file.h"
7 #include "static_threads.h"
8 #include "web/api/queries/backfill.h"
9 #include "web/mcp/mcp.h"
10
11 #include "database/engine/page_test.h"
12 #include "database/rrdset-slots.h"
13 #include <curl/curl.h>
14
15 #ifdef OS_WINDOWS
16 #include "win_system-info.h"
17 #endif
18
19 #ifdef ENABLE_SENTRY
20 #include "sentry-native/sentry-native.h"
21 #endif
22
23 #if defined(ENV32BIT)
24 #warning COMPILING 32BIT NETDATA
25 #endif
26
27 bool unittest_running = false;
28 bool netdata_anonymous_statistics_enabled = true;
29
30 int libuv_worker_threads = MIN_LIBUV_WORKER_THREADS;
31 bool ieee754_doubles = false;
32 time_t netdata_start_time = 0;
33 struct netdata_static_thread *static_threads;
34
35 static void set_nofile_limit(struct rlimit *rl) {
36 // get the num files allowed
37 if(getrlimit(RLIMIT_NOFILE, rl) != 0) {
38 netdata_log_error("getrlimit(RLIMIT_NOFILE) failed");
39 return;
40 }
41
42 netdata_log_info("resources control: allowed file descriptors: soft = %zu, max = %zu",
43 (size_t) rl->rlim_cur, (size_t) rl->rlim_max);
44
45 // make the soft/hard limits equal
46 rl->rlim_cur = rl->rlim_max;
47 if (setrlimit(RLIMIT_NOFILE, rl) != 0) {
48 netdata_log_error("setrlimit(RLIMIT_NOFILE, { %zu, %zu }) failed", (size_t)rl->rlim_cur, (size_t)rl->rlim_max);
49 }
50
51 // sanity check to make sure we have enough file descriptors available to open
52 if (getrlimit(RLIMIT_NOFILE, rl) != 0) {
53 netdata_log_error("getrlimit(RLIMIT_NOFILE) failed");
54 return;
55 }
56
57 if (rl->rlim_cur < 1024)
58 netdata_log_error("Number of open file descriptors allowed for this process is too low (RLIMIT_NOFILE=%zu)", (size_t)rl->rlim_cur);
59 }
60
61 static const struct option_def {
62 const char val;
63 const char *description;
64 const char *arg_name;
65 const char *default_value;
66 } option_definitions[] = {
67 {'c', "Configuration file to load.", "filename", CONFIG_DIR "/" CONFIG_FILENAME},
68 {'D', "Do not fork. Run in the foreground.", NULL, "run in the background"},
69 {'d', "Fork. Run in the background.", NULL, "run in the background"},
70 {'h', "Display this help message.", NULL, NULL},
71 {'P', "File to save a pid while running.", "filename", "do not save pid to a file"},
72 {'i', "The IP address to listen to.", "IP", "all IP addresses IPv4 and IPv6"},
73 {'p', "API/Web port to use.", "port", "19999"},
74 {'s', "Prefix for /proc and /sys (for containers).", "path", "no prefix"},
75 {'t', "The internal clock of netdata.", "seconds", "1"},
76 {'u', "Run as user.", "username", "netdata"},
77 {'v', "Print netdata version and exit.", NULL, NULL},
78 {'V', "Print netdata version and exit.", NULL, NULL},
79 {'W', "See Advanced options below.", "options", NULL},
80 };
81
82 int help(int exitcode) {
83 FILE *stream;
84 if(exitcode == 0)
85 stream = stdout;
86 else
87 stream = stderr;
88
89 int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
90 int i;
91 int max_len_arg = 0;
92
93 // Compute maximum argument length
94 for( i = 0; i < num_opts; i++ ) {
95 if(option_definitions[i].arg_name) {
96 int len_arg = (int)strlen(option_definitions[i].arg_name);
97 if(len_arg > max_len_arg) max_len_arg = len_arg;
98 }
99 }
100
101 if(max_len_arg > 30) max_len_arg = 30;
102 if(max_len_arg < 20) max_len_arg = 20;
103
104 fprintf(stream, "%s", "\n"
105 " ^\n"
106 " |.-. .-. .-. .-. . Netdata \n"
107 " | '-' '-' '-' '-' X-Ray Vision for your infrastructure! \n"
108 " +----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+--->\n"
109 "\n"
110 " Copyright 2018-2025 Netdata Inc.\n"
111 " Released under GNU General Public License v3 or later.\n"
112 "\n"
113 " Home Page : https://netdata.cloud\n"
114 " Source Code: https://github.com/netdata/netdata\n"
115 " Docs : https://learn.netdata.cloud\n"
116 " Support : https://github.com/netdata/netdata/issues\n"
117 " License : https://github.com/netdata/netdata/blob/master/LICENSE.md\n"
118 "\n"
119 " Twitter : https://twitter.com/netdatahq\n"
120 " LinkedIn : https://linkedin.com/company/netdata-cloud/\n"
121 " Facebook : https://facebook.com/linuxnetdata/\n"
122 "\n"
123 "\n"
124 );
125
126 fprintf(stream, " SYNOPSIS: netdata [options]\n");
127 fprintf(stream, "\n");
128 fprintf(stream, " Options:\n\n");
129
130 // Output options description.
131 for( i = 0; i < num_opts; i++ ) {
132 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);
133 if(option_definitions[i].default_value) {
134 fprintf(stream, "\n %c %-*s Default: %s\n", ' ', max_len_arg, "", option_definitions[i].default_value);
135 } else {
136 fprintf(stream, "\n");
137 }
138 fprintf(stream, "\n");
139 }
140
141 fprintf(stream, "\n Advanced options:\n\n"
142 " -W stacksize=N Set the stacksize (in bytes).\n\n"
143 " -W debug_flags=N Set runtime tracing to debug.log.\n\n"
144 " -W unittest Run internal unittests and exit.\n\n"
145 " -W sqlite-meta-recover Run recovery on the metadata database and exit.\n\n"
146 " -W sqlite-compact Reclaim metadata database unused space and exit.\n\n"
147 " -W sqlite-analyze Run update statistics and exit.\n\n"
148 " -W sqlite-alert-cleanup Perform maintenance on the alerts table.\n\n"
149 #ifdef ENABLE_DBENGINE
150 " -W createdataset=N Create a DB engine dataset of N seconds and exit.\n\n"
151 " -W stresstest=A,B,C,D,E,F,G\n"
152 " Run a DB engine stress test for A seconds,\n"
153 " with B writers and C readers, with a ramp up\n"
154 " time of D seconds for writers, a page cache\n"
155 " size of E MiB, an optional disk space limit\n"
156 " of F MiB, G libuv workers (default 16) and exit.\n\n"
157 #endif
158 " -W prd-array-stress Run PRD_ARRAY refcount stress test and exit.\n\n"
159 " -W set section option value\n"
160 " set netdata.conf option from the command line.\n\n"
161 " -W buildinfo Print the version, the configure options,\n"
162 " a list of optional features, and whether they\n"
163 " are enabled or not.\n\n"
164 " -W buildinfojson Print the version, the configure options,\n"
165 " a list of optional features, and whether they\n"
166 " are enabled or not, in JSON format.\n\n"
167 " -W cmakecache Print the cmake cache used for building this agent\n"
168 " -W simple-pattern pattern string\n"
169 " Check if string matches pattern and exit.\n\n"
170 #ifdef OS_WINDOWS
171 " -W perflibdump [key]\n"
172 " Dump the Windows Performance Counters Registry in JSON.\n\n"
173 #endif
174 );
175
176 fprintf(stream, "\n Signals netdata handles:\n\n"
177 " - HUP Close and reopen log files.\n"
178 " - USR2 Reload health configuration.\n"
179 "\n"
180 );
181
182 fflush(stream);
183 return exitcode;
184 }
185
186 /* Any config setting that can be accessed without a default value i.e. configget(...,...,NULL) *MUST*
187 be set in this procedure to be called in all the relevant code paths.
188 */
189
190 #if defined(FSANITIZE_ADDRESS)
191 #define LOG_TO_STDERR(...) fprintf(stdout, __VA_ARGS__)
192 #else
193 #define LOG_TO_STDERR(...)
194 #endif
195
196 #define delta_startup_time(msg) \
197 do { \
198 usec_t now_ut = now_monotonic_usec(); \
199 if(prev_msg) { \
200 netdata_log_info("NETDATA STARTUP: in %7llu ms, %s - next: %s", (now_ut - last_ut) / USEC_PER_MS, prev_msg, msg); \
201 LOG_TO_STDERR(" > startup: in %7llu ms, %s - next: %s\n", (now_ut - last_ut) / USEC_PER_MS, prev_msg, msg); \
202 } \
203 else { \
204 netdata_log_info("NETDATA STARTUP: next: %s", msg); \
205 LOG_TO_STDERR(" > startup: next: %s\n", msg); \
206 } \
207 last_ut = now_ut; \
208 prev_msg = msg; \
209 daemon_status_file_startup_step("startup(" msg ")"); \
210 } while(0)
211
212 int buffer_unittest(void);
213 int pgc_unittest(void);
214 int mrg_unittest(void);
215 int pluginsd_parser_unittest(void);
216 void replication_initialize(void);
217 void bearer_tokens_init(void);
218 int unittest_stream_compressions(void);
219 int uuid_unittest(void);
220 int progress_unittest(void);
221 int dyncfg_unittest(void);
222 int eval_unittest(void);
223 int duration_unittest(void);
224 int statistical_unittest(void);
225 int health_config_unittest(void);
226 int utf8_sanitizer_unittest(void);
227 int yaml_unittest(void);
228 int json_c_parser_unittest(void);
229 int query_plan_unittest(void);
230 #ifdef ENABLE_ML
231 int ml_unittest(void);
232 #endif
233 bool netdata_random_session_id_generate(void);
234
235 #ifdef OS_WINDOWS
236 int windows_perflib_dump(const char *key);
237 #endif
238
239 int unittest_prepare_rrd(const char **user) {
240 netdata_conf_section_global_run_as_user(user);
241 netdata_conf_section_global();
242 nd_profile.update_every = 1;
243 default_rrd_memory_mode = RRD_DB_MODE_RAM;
244 health_plugin_disable();
245 nd_profile.storage_tiers = 1;
246 registry_init();
247 if(rrd_init("unittest", NULL, true)) {
248 fprintf(stderr, "rrd_init failed for unittest\n");
249 return 1;
250 }
251 stream_send.enabled = false;
252
253 return 0;
254 }
255
256 static void fatal_status_file_save(void) {
257 daemon_status_file_update_status(DAEMON_STATUS_NONE);
258 exit(1);
259 }
260
261 int netdata_main(int argc, char **argv) {
262 libjudy_malloc_init();
263 string_init();
264 analytics_init();
265 nd_log_initialize_mutexes();
266
267 // Register the daemon's per-thread cleanup callback. Each subsystem
268 // should own the registration of its own cleanups; this one lives in
269 // the daemon because service_exits is a daemon-layer concern. The
270 // rest are currently registered together in rrd_init() and should be
271 // moved to their respective subsystems in a follow-up.
272 nd_thread_register_cleanup(service_exits);
273
274 netdata_start_time = now_realtime_sec();
275 usec_t started_ut = now_monotonic_usec();
276 usec_t last_ut = started_ut;
277 const char *prev_msg = NULL;
278
279 int i;
280 int config_loaded = 0;
281 bool close_open_fds = true; (void)close_open_fds;
282 const char *user = NULL;
283
284 #ifdef OS_WINDOWS
285 int dont_fork = 1;
286 #else
287 int dont_fork = 0;
288 #endif
289
290 static_threads = static_threads_get();
291
292 netdata_ready_store(false);
293 // set the name for logging
294 program_name = "netdata";
295
296 curl_global_init(CURL_GLOBAL_ALL);
297
298 // parse options
299 {
300 int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
301 char optstring[(sizeof(option_definitions) / sizeof(option_definitions[0]) * 2) + 1];
302
303 int string_i = 0;
304 for( i = 0; i < num_opts; i++ ) {
305 optstring[string_i] = option_definitions[i].val;
306 string_i++;
307 if(option_definitions[i].arg_name) {
308 optstring[string_i] = ':';
309 string_i++;
310 }
311 }
312 // terminate optstring
313 optstring[string_i] ='\0';
314 optstring[(num_opts *2)] ='\0';
315
316 int opt;
317 while( (opt = getopt(argc, argv, optstring)) != -1 ) {
318 switch(opt) {
319 case 'c':
320 if(!netdata_conf_load(optarg, 1, &user)) {
321 netdata_log_error("Cannot load configuration file %s.", optarg);
322 return 1;
323 }
324 else {
325 netdata_log_debug(D_OPTIONS, "Configuration loaded from %s.", optarg);
326 cloud_conf_load(1);
327 config_loaded = 1;
328 }
329 break;
330 case 'D':
331 dont_fork = 1;
332 break;
333 case 'd':
334 dont_fork = 0;
335 break;
336 case 'h':
337 return help(0);
338 case 'i':
339 inicfg_set(&netdata_config, CONFIG_SECTION_WEB, "bind to", optarg);
340 break;
341 case 'P':
342 pidfile = strdupz(optarg);
343 break;
344 case 'p':
345 inicfg_set(&netdata_config, CONFIG_SECTION_GLOBAL, "default port", optarg);
346 break;
347 case 's':
348 inicfg_set(&netdata_config, CONFIG_SECTION_GLOBAL, "host access prefix", optarg);
349 break;
350 case 't':
351 inicfg_set(&netdata_config, CONFIG_SECTION_GLOBAL, "update every", optarg);
352 break;
353 case 'u':
354 inicfg_set(&netdata_config, CONFIG_SECTION_GLOBAL, "run as user", optarg);
355 break;
356 case 'v':
357 case 'V':
358 printf("%s %s\n", program_name, NETDATA_VERSION);
359 return 0;
360 case 'W':
361 {
362 char* stacksize_string = "stacksize=";
363 char* debug_flags_string = "debug_flags=";
364 #ifdef ENABLE_DBENGINE
365 char* createdataset_string = "createdataset=";
366 char* stresstest_string = "stresstest=";
367
368 if(strcmp(optarg, "pgd-tests") == 0) {
369 return pgd_test(argc, argv);
370 }
371 #endif
372
373 if(strcmp(optarg, "sqlite-meta-recover") == 0) {
374 sql_init_meta_database(DB_CHECK_RECOVER, 0);
375 return 0;
376 }
377
378 if(strcmp(optarg, "sqlite-compact") == 0) {
379 sql_init_meta_database(DB_CHECK_RECLAIM_SPACE, 0);
380 return 0;
381 }
382
383 if(strcmp(optarg, "sqlite-analyze") == 0) {
384 sql_init_meta_database(DB_CHECK_ANALYZE, 0);
385 return 0;
386 }
387
388 if(strcmp(optarg, "sqlite-alert-cleanup") == 0) {
389 sql_alert_cleanup(true);
390 return 0;
391 }
392
393 if(strcmp(optarg, "jsonctest") == 0) {
394 unittest_running = true;
395 if (json_c_parser_unittest()) return 1;
396 fprintf(stderr, "\n\nJSON-C PARSER TESTS PASSED\n\n");
397 return 0;
398 }
399
400 if(strcmp(optarg, "yamltest") == 0) {
401 unittest_running = true;
402 if (yaml_unittest()) return 1;
403 fprintf(stderr, "\n\nYAML TESTS PASSED\n\n");
404 return 0;
405 }
406
407 if(strcmp(optarg, "mltest") == 0) {
408 #ifdef ENABLE_ML
409 unittest_running = true;
410 if (ml_unittest()) return 1;
411 fprintf(stderr, "\n\nML TESTS PASSED\n\n");
412 return 0;
413 #else
414 fprintf(stderr, "ML support is disabled in this build.\n");
415 return 1;
416 #endif
417 }
418
419 if(strcmp(optarg, "unittest") == 0) {
420 unittest_running = true;
421
422 // set defaults for dbegnine unittest
423 inicfg_set(&netdata_config, CONFIG_SECTION_DB, "dbengine page type", "gorilla");
424 #ifdef ENABLE_DBENGINE
425 default_rrdeng_disk_quota_mb = default_multidb_disk_quota_mb = 256;
426 #endif
427
428 if (sqlite_library_init())
429 return 1;
430 rrdlabels_aral_init(false);
431
432 if (pluginsd_parser_unittest()) return 1;
433 if (unit_test_static_threads()) return 1;
434 if (unit_test_buffer()) return 1;
435 if (unit_test_str2ld()) return 1;
436 if (buffer_unittest()) return 1;
437
438 // No call to load the config file on this code-path
439 if (unittest_prepare_rrd(&user)) return 1;
440 if (run_all_mockup_tests()) return 1;
441 if (unit_test_storage()) return 1;
442 #ifdef ENABLE_DBENGINE
443 if (test_dbengine()) return 1;
444 #endif
445 if (test_sqlite()) return 1;
446 if (string_unittest(10000)) return 1;
447 if (dictionary_unittest(10000)) return 1;
448 if (aral_unittest(10000)) return 1;
449 if (rrdlabels_unittest()) return 1;
450 if (rrdhost_labels_unittest()) return 1;
451 if (ctx_unittest()) return 1;
452 if (query_plan_unittest()) return 1;
453 if (uuid_unittest()) return 1;
454 if (dyncfg_unittest()) return 1;
455 if (eval_unittest()) return 1;
456 if (duration_unittest()) return 1;
457 if (statistical_unittest()) return 1;
458 if (utf8_sanitizer_unittest()) return 1;
459 if (health_config_unittest()) return 1;
460 if (yaml_unittest()) return 1;
461 if (json_c_parser_unittest()) return 1;
462 if (unittest_waiting_queue()) return 1;
463 if (rw_spinlock_unittest()) return 1;
464 if (uuidmap_unittest()) return 1;
465 #ifdef HAVE_LIBBACKTRACE
466 if (stacktrace_unittest()) return 1;
467 #endif
468 if (test_cmd_pool_fifo()) return 1;
469 #ifdef OS_WINDOWS
470 if (perflibnamestest_main()) return 1;
471 #endif
472 sqlite_library_shutdown();
473 rrdlabels_aral_destroy(false);
474 fprintf(stderr, "\n\nALL TESTS PASSED\n\n");
475 return 0;
476 }
477 else if(strcmp(optarg, "escapetest") == 0) {
478 return command_argument_sanitization_tests();
479 }
480 else if(strcmp(optarg, "dicttest") == 0) {
481 unittest_running = true;
482 return dictionary_unittest(10000);
483 }
484 else if(strcmp(optarg, "dicttest-benchmark") == 0) {
485 unittest_running = true;
486 return dictionary_unittest_benchmark();
487 }
488 else if(strcmp(optarg, "araltest") == 0) {
489 unittest_running = true;
490 return aral_unittest(10000);
491 }
492 else if(strcmp(optarg, "aralconcurrency") == 0) {
493 unittest_running = true;
494 #ifdef NETDATA_INTERNAL_CHECKS
495 return aral_unittest_concurrency();
496 #else
497 fprintf(stderr, "aralconcurrency requires NETDATA_INTERNAL_CHECKS\n");
498 return 1;
499 #endif
500 }
501 else if(strcmp(optarg, "waitqtest") == 0) {
502 unittest_running = true;
503 return unittest_waiting_queue();
504 }
505 else if(strcmp(optarg, "uuidmaptest") == 0) {
506 unittest_running = true;
507 return uuidmap_unittest();
508 }
509 else if(strcmp(optarg, "lockstest") == 0) {
510 unittest_running = true;
511 return locks_stress_test();
512 }
513 else if(strcmp(optarg, "rwlockstest") == 0) {
514 unittest_running = true;
515 return rwlocks_stress_test();
516 }
517 else if(strcmp(optarg, "rwspinlocktest") == 0) {
518 unittest_running = true;
519 return rw_spinlock_unittest();
520 }
521 else if(strcmp(optarg, "prd-array-stress") == 0) {
522 unittest_running = true;
523 return prd_array_stress_test();
524 }
525 else if(strcmp(optarg, "stringtest") == 0) {
526 unittest_running = true;
527 return string_unittest(10000);
528 }
529 else if(strcmp(optarg, "rrdlabelstest") == 0) {
530 unittest_running = true;
531 rrdlabels_aral_init(true);
532 int rc = rrdlabels_unittest();
533 rrdlabels_aral_destroy(true);
534 return rc;
535 }
536 else if(strcmp(optarg, "buffertest") == 0) {
537 unittest_running = true;
538 return buffer_unittest();
539 }
540 else if(strcmp(optarg, "test_cmd_pool_fifo") == 0) {
541 unittest_running = true;
542 return test_cmd_pool_fifo();
543 }
544 else if(strcmp(optarg, "uuidtest") == 0) {
545 unittest_running = true;
546 return uuid_unittest();
547 }
548 #ifdef HAVE_LIBBACKTRACE
549 else if(strcmp(optarg, "stacktracetest") == 0) {
550 unittest_running = true;
551 return stacktrace_unittest();
552 }
553 #endif
554 #ifdef OS_WINDOWS
555 else if(strcmp(optarg, "perflibdump") == 0) {
556 return windows_perflib_dump(optind + 1 > argc ? NULL : argv[optind]);
557 }
558 else if(strcmp(optarg, "perflibnamestest") == 0) {
559 unittest_running = true;
560 return perflibnamestest_main();
561 }
562 #endif
563 else if(strcmp(optarg, "utf8sanitizertest") == 0) {
564 unittest_running = true;
565 return utf8_sanitizer_unittest();
566 }
567 else if(strcmp(optarg, "queryplantest") == 0) {
568 unittest_running = true;
569 return query_plan_unittest();
570 }
571 #ifdef ENABLE_DBENGINE
572 else if(strcmp(optarg, "mctest") == 0) {
573 unittest_running = true;
574 return mc_unittest();
575 }
576 else if(strcmp(optarg, "ctxtest") == 0) {
577 unittest_running = true;
578 return ctx_unittest();
579 }
580 else if(strcmp(optarg, "metatest") == 0) {
581 unittest_running = true;
582 return metadata_unittest();
583 }
584 else if(strcmp(optarg, "pgctest") == 0) {
585 unittest_running = true;
586 return pgc_unittest();
587 }
588 else if(strcmp(optarg, "mrgtest") == 0) {
589 unittest_running = true;
590 return mrg_unittest();
591 }
592 else if(strcmp(optarg, "mrgretentionbench") == 0) {
593 unittest_running = true;
594 return mrg_retention_benchmark();
595 }
596 else if(strcmp(optarg, "parsertest") == 0) {
597 unittest_running = true;
598 return pluginsd_parser_unittest();
599 }
600 else if(strcmp(optarg, "stream_compressions_test") == 0) {
601 unittest_running = true;
602 return unittest_stream_compressions();
603 }
604 else if(strcmp(optarg, "progresstest") == 0) {
605 unittest_running = true;
606 return progress_unittest();
607 }
608 else if(strcmp(optarg, "evaltest") == 0) {
609 unittest_running = true;
610 return eval_unittest();
611 }
612 else if(strcmp(optarg, "durationtest") == 0) {
613 unittest_running = true;
614 return duration_unittest();
615 }
616 else if(strcmp(optarg, "healthconfigtest") == 0) {
617 unittest_running = true;
618 return health_config_unittest();
619 }
620 else if(strcmp(optarg, "dyncfgtest") == 0) {
621 unittest_running = true;
622 if(sqlite_library_init())
623 return 1;
624 rrdlabels_aral_init(false);
625
626 int rc = unittest_prepare_rrd(&user);
627 if (!rc)
628 rc = dyncfg_unittest();
629
630 sqlite_close_databases();
631 sqlite_library_shutdown();
632 rrdlabels_aral_destroy(false);
633 return rc;
634 }
635 else if(strncmp(optarg, createdataset_string, strlen(createdataset_string)) == 0) {
636 optarg += strlen(createdataset_string);
637 unsigned history_seconds = strtoul(optarg, NULL, 0);
638 netdata_conf_section_global_run_as_user(&user);
639 netdata_conf_section_global();
640 nd_profile.update_every = 1;
641 registry_init();
642 if(rrd_init("dbengine-dataset", NULL, true)) {
643 fprintf(stderr, "rrd_init failed for unittest\n");
644 return 1;
645 }
646 generate_dbengine_dataset(history_seconds);
647 return 0;
648 }
649 else if(strncmp(optarg, stresstest_string, strlen(stresstest_string)) == 0) {
650 char *endptr;
651 unsigned test_duration_sec = 0, dset_charts = 0, query_threads = 0, ramp_up_seconds = 0,
652 page_cache_mb = 0, disk_space_mb = 0, workers = 16;
653
654 optarg += strlen(stresstest_string);
655 test_duration_sec = (unsigned)strtoul(optarg, &endptr, 0);
656 if (',' == *endptr)
657 dset_charts = (unsigned)strtoul(endptr + 1, &endptr, 0);
658 if (',' == *endptr)
659 query_threads = (unsigned)strtoul(endptr + 1, &endptr, 0);
660 if (',' == *endptr)
661 ramp_up_seconds = (unsigned)strtoul(endptr + 1, &endptr, 0);
662 if (',' == *endptr)
663 page_cache_mb = (unsigned)strtoul(endptr + 1, &endptr, 0);
664 if (',' == *endptr)
665 disk_space_mb = (unsigned)strtoul(endptr + 1, &endptr, 0);
666 if (',' == *endptr)
667 workers = (unsigned)strtoul(endptr + 1, &endptr, 0);
668
669 if (workers > 1024)
670 workers = 1024;
671
672 char workers_str[16];
673 snprintf(workers_str, 15, "%u", workers);
674 setenv("UV_THREADPOOL_SIZE", workers_str, 1);
675 dbengine_stress_test(test_duration_sec, dset_charts, query_threads, ramp_up_seconds,
676 page_cache_mb, disk_space_mb);
677 return 0;
678 }
679 #endif
680 else if(strcmp(optarg, "simple-pattern") == 0) {
681 if(optind + 2 > argc) {
682 fprintf(stderr, "%s", "\nUSAGE: -W simple-pattern 'pattern' 'string'\n\n"
683 " Checks if 'pattern' matches the given 'string'.\n"
684 " - 'pattern' can be one or more space separated words.\n"
685 " - each 'word' can contain one or more asterisks.\n"
686 " - words starting with '!' give negative matches.\n"
687 " - words are processed left to right\n"
688 "\n"
689 "Examples:\n"
690 "\n"
691 " > match all veth interfaces, except veth0:\n"
692 "\n"
693 " -W simple-pattern '!veth0 veth*' 'veth12'\n"
694 "\n"
695 "\n"
696 " > match all *.ext files directly in /path/:\n"
697 " (this will not match *.ext files in a subdir of /path/)\n"
698 "\n"
699 " -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n"
700 "\n"
701 );
702 return 1;
703 }
704
705 const char *haystack = argv[optind];
706 const char *needle = argv[optind + 1];
707 size_t len = strlen(needle) + 1;
708 CLEAN_CHAR_P *wildcarded = mallocz(len);
709
710 SIMPLE_PATTERN *p = simple_pattern_create(haystack, NULL, SIMPLE_PATTERN_EXACT, true);
711 SIMPLE_PATTERN_RESULT ret = simple_pattern_matches_extract(p, needle, wildcarded, len);
712 simple_pattern_free(p);
713
714 if(ret == SP_MATCHED_POSITIVE) {
715 fprintf(stdout, "RESULT: POSITIVE MATCHED - pattern '%s' matches '%s', wildcarded '%s'\n", haystack, needle, wildcarded);
716 return 0;
717 }
718 else if(ret == SP_MATCHED_NEGATIVE) {
719 fprintf(stdout, "RESULT: NEGATIVE MATCHED - pattern '%s' matches '%s', wildcarded '%s'\n", haystack, needle, wildcarded);
720 return 0;
721 }
722 else {
723 fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s', wildcarded '%s'\n", haystack, needle, wildcarded);
724 return 1;
725 }
726 }
727 else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) {
728 optarg += strlen(stacksize_string);
729 inicfg_set(&netdata_config, CONFIG_SECTION_GLOBAL, "pthread stack size", optarg);
730 }
731 else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) {
732 optarg += strlen(debug_flags_string);
733 inicfg_set(&netdata_config, CONFIG_SECTION_LOGS, "debug flags", optarg);
734 debug_flags = strtoull(optarg, NULL, 0);
735 }
736 else if(strcmp(optarg, "set") == 0) {
737 if(optind + 3 > argc) {
738 fprintf(stderr, "%s", "\nUSAGE: -W set 'section' 'key' 'value'\n\n"
739 " Overwrites settings of netdata.conf.\n"
740 "\n"
741 " These options interact with: -c netdata.conf\n"
742 " If -c netdata.conf is given on the command line,\n"
743 " before -W set... the user may overwrite command\n"
744 " line parameters at netdata.conf\n"
745 " If -c netdata.conf is given after (or missing)\n"
746 " -W set... the user cannot overwrite the command line\n"
747 " parameters."
748 "\n"
749 );
750 return 1;
751 }
752 const char *section = argv[optind];
753 const char *key = argv[optind + 1];
754 const char *value = argv[optind + 2];
755 optind += 3;
756
757 // set this one as the default
758 // only if it is not already set in the config file
759 // so the caller can use -c netdata.conf before or
760 // after this parameter to prevent or allow overwriting
761 // variables at netdata.conf
762 inicfg_set_default_raw_value(&netdata_config, section, key, value);
763
764 // fprintf(stderr, "SET section '%s', key '%s', value '%s'\n", section, key, value);
765 }
766 else if(strcmp(optarg, "set2") == 0) {
767 if(optind + 4 > argc) {
768 fprintf(stderr, "%s", "\nUSAGE: -W set 'conf_file' 'section' 'key' 'value'\n\n"
769 " Overwrites settings of netdata.conf or cloud.conf\n"
770 "\n"
771 " These options interact with: -c netdata.conf\n"
772 " If -c netdata.conf is given on the command line,\n"
773 " before -W set... the user may overwrite command\n"
774 " line parameters at netdata.conf\n"
775 " If -c netdata.conf is given after (or missing)\n"
776 " -W set... the user cannot overwrite the command line\n"
777 " parameters."
778 " conf_file can be \"cloud\" or \"netdata\".\n"
779 "\n"
780 );
781 return 1;
782 }
783 const char *conf_file = argv[optind]; /* "cloud" is cloud.conf, otherwise netdata.conf */
784 struct config *tmp_config = strcmp(conf_file, "cloud") ? &netdata_config : &cloud_config;
785 const char *section = argv[optind + 1];
786 const char *key = argv[optind + 2];
787 const char *value = argv[optind + 3];
788 optind += 4;
789
790 // set this one as the default
791 // only if it is not already set in the config file
792 // so the caller can use -c netdata.conf before or
793 // after this parameter to prevent or allow overwriting
794 // variables at netdata.conf
795 inicfg_set_default_raw_value(tmp_config, section, key, value);
796
797 // fprintf(stderr, "SET section '%s', key '%s', value '%s'\n", section, key, value);
798 }
799 else if(strcmp(optarg, "get") == 0) {
800 if(optind + 3 > argc) {
801 fprintf(stderr, "%s", "\nUSAGE: -W get 'section' 'key' 'value'\n\n"
802 " Prints settings of netdata.conf.\n"
803 "\n"
804 " These options interact with: -c netdata.conf\n"
805 " -c netdata.conf has to be given before -W get.\n"
806 "\n"
807 );
808 return 1;
809 }
810
811 if(!config_loaded) {
812 fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n");
813 netdata_conf_load(NULL, 0, &user);
814 }
815
816 netdata_conf_section_global();
817
818 const char *section = argv[optind];
819 const char *key = argv[optind + 1];
820 const char *def = argv[optind + 2];
821 const char *value = inicfg_get(&netdata_config, section, key, def);
822 printf("%s\n", value);
823 return 0;
824 }
825 else if(strcmp(optarg, "get2") == 0) {
826 if(optind + 4 > argc) {
827 fprintf(stderr, "%s", "\nUSAGE: -W get2 'conf_file' 'section' 'key' 'value'\n\n"
828 " Prints settings of netdata.conf or cloud.conf\n"
829 "\n"
830 " These options interact with: -c netdata.conf\n"
831 " -c netdata.conf has to be given before -W get2.\n"
832 " conf_file can be \"cloud\" or \"netdata\".\n"
833 "\n"
834 );
835 return 1;
836 }
837
838 if(!config_loaded) {
839 fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n");
840 netdata_conf_load(NULL, 0, &user);
841 cloud_conf_load(1);
842 }
843
844 netdata_conf_section_global();
845
846 const char *conf_file = argv[optind]; /* "cloud" is cloud.conf, otherwise netdata.conf */
847 struct config *tmp_config = strcmp(conf_file, "cloud") ? &netdata_config : &cloud_config;
848 const char *section = argv[optind + 1];
849 const char *key = argv[optind + 2];
850 const char *def = argv[optind + 3];
851 const char *value = inicfg_get(tmp_config, section, key, def);
852 printf("%s\n", value);
853 return 0;
854 }
855 else if(strcmp(optarg, "buildinfo") == 0) {
856 print_build_info();
857 return 0;
858 }
859 else if(strcmp(optarg, "buildinfojson") == 0) {
860 print_build_info_json();
861 return 0;
862 }
863 else if(strcmp(optarg, "cmakecache") == 0) {
864 print_build_info_cmake_cache();
865 return 0;
866 }
867 else if(strcmp(optarg, "keepopenfds") == 0) {
868 // Internal dev option to skip closing inherited
869 // open FDs. Useful, when we want to run the agent
870 // under profiling tools that open/maintain their
871 // own FDs.
872 close_open_fds = false;
873 } else {
874 fprintf(stderr, "Unknown -W parameter '%s'\n", optarg);
875 return help(1);
876 }
877 }
878 break;
879
880 default: /* ? */
881 fprintf(stderr, "Unknown parameter '%c'\n", opt);
882 return help(1);
883 }
884 }
885 }
886
887 #if !defined(FSANITIZE_ADDRESS)
888 if (close_open_fds == true) {
889 // close all open file descriptors, except the standard ones
890 // the caller may have left open files (lxc-attach has this issue)
891 os_close_all_non_std_open_fds_except(NULL, 0, 0);
892 }
893 #else
894 fprintf(stderr, "Running with a Sanitizer, custom allocators are disabled.\n");
895 fprintf(stderr, "Running with a Sanitizer, not closing open fds.\n");
896 #endif
897
898 if(!config_loaded) {
899 netdata_conf_load(NULL, 0, &user);
900 cloud_conf_load(0);
901 }
902
903 // ----------------------------------------------------------------------------------------------------------------
904 // initialize the logging system
905 // IMPORTANT: KEEP THIS FIRST SO THAT THE REST OF NETDATA WILL LOG PROPERLY
906
907 netdata_conf_section_directories();
908 netdata_conf_section_logs();
909 nd_log_limits_unlimited();
910 nd_log_initialize();
911
912 // ----------------------------------------------------------------------------------------------------------------
913 // this MUST be before anything else - to load the old status file before saving a new one
914
915 daemon_status_file_init(); // this loads the old file
916 machine_guid_get(); // after loading the old daemon status file - we may need the machine guid from it
917 nd_log_register_fatal_hook_cb(daemon_status_file_register_fatal);
918 nd_log_register_fatal_final_cb(fatal_status_file_save);
919 exit_initiated_init();
920
921 // ----------------------------------------------------------------------------------------------------------------
922 delta_startup_time("signals");
923
924 signals_block_all_except_deadly();
925 nd_initialize_signals(false); // catches deadly signals and stores them in the status file
926
927 // ----------------------------------------------------------------------------------------------------------------
928
929 netdata_conf_section_global(); // get hostname, host prefix, profile, etc
930 registry_init(); // for machine_guid, must be after netdata_conf_section_global()
931
932 // ----------------------------------------------------------------------------------------------------------------
933 delta_startup_time("run dir");
934
935 {
936 const char *run_dir = os_run_dir(true);
937 if(!run_dir) {
938 netdata_log_error("Cannot get/create a run directory.");
939 exit(1);
940 }
941 netdata_log_info("Netdata run directory is '%s'", run_dir);
942
943 // char lock_file[FILENAME_MAX];
944 // snprintfz(lock_file, sizeof(lock_file), "%s/netdata.lock", run_dir);
945 // FILE_LOCK lock = file_lock_get(lock_file);
946 // if(!FILE_LOCK_OK(lock)) {
947 // netdata_log_error("Cannot get exclusive lock on file '%s'. Is Netdata already running?", lock_file);
948 // exit(1);
949 // }
950 }
951
952 nd_profile_setup();
953
954 // ----------------------------------------------------------------------------------------------------------------
955 delta_startup_time("crash reports");
956
957 daemon_status_file_check_crash();
958
959 // ----------------------------------------------------------------------------------------------------------------
960 delta_startup_time("temp spawn server");
961 netdata_main_spawn_server_init("init", argc, (const char **)argv);
962
963 // ----------------------------------------------------------------------------------------------------------------
964 delta_startup_time("ssl");
965
966 netdata_conf_ssl();
967
968 // ----------------------------------------------------------------------------------------------------------------
969 delta_startup_time("environment for plugins");
970
971 // prepare configuration environment variables for the plugins
972 set_environment_for_plugins_and_scripts();
973
974 // ----------------------------------------------------------------------------------------------------------------
975 delta_startup_time("cd to user config dir");
976
977 // cd into config_dir to allow the plugins refer to their config files using relative filenames
978 if(chdir(netdata_configured_user_config_dir) == -1)
979 fatal("Cannot cd to '%s'", netdata_configured_user_config_dir);
980
981 // ----------------------------------------------------------------------------------------------------------------
982 delta_startup_time("analytics");
983
984 analytics_reset();
985 get_system_timezone();
986 rrdlabels_aral_init(true);
987
988 // ----------------------------------------------------------------------------------------------------------------
989 delta_startup_time("pulse");
990
991 #ifdef NETDATA_INTERNAL_CHECKS
992 pulse_enabled = true;
993 pulse_extended_enabled = true;
994 #endif
995
996 pulse_extended_enabled =
997 inicfg_get_boolean(&netdata_config, CONFIG_SECTION_PULSE, "extended", pulse_extended_enabled);
998
999 if(pulse_extended_enabled)
1000 // this has to run before starting any other threads that use workers
1001 workers_utilization_enable();
1002
1003 // ----------------------------------------------------------------------------------------------------------------
1004 delta_startup_time("replication");
1005
1006 replication_initialize();
1007
1008 // ----------------------------------------------------------------------------------------------------------------
1009 delta_startup_time("inflight functions");
1010
1011 rrd_functions_inflight_init();
1012
1013 // ----------------------------------------------------------------------------------------------------------------
1014 delta_startup_time("silencers");
1015
1016 health_set_silencers_filename();
1017 health_initialize_global_silencers();
1018
1019 // ----------------------------------------------------------------------------------------------------------------
1020 delta_startup_time("static threads");
1021
1022 for (i = 0; static_threads[i].name != NULL ; i++) {
1023 struct netdata_static_thread *st = &static_threads[i];
1024
1025 if(st->enable_routine)
1026 st->enabled = st->enable_routine();
1027
1028 if(st->config_name)
1029 st->enabled = inicfg_get_boolean(&netdata_config, st->config_section, st->config_name, st->enabled);
1030
1031 if(st->enabled && st->init_routine)
1032 st->init_routine();
1033
1034 if(st->env_name)
1035 nd_setenv(st->env_name, st->enabled?"YES":"NO", 1);
1036
1037 if(st->global_variable)
1038 *st->global_variable = (st->enabled) ? true : false;
1039 }
1040
1041 // ----------------------------------------------------------------------------------------------------------------
1042 delta_startup_time("web server api");
1043
1044 // get the certificate and start security
1045 netdata_conf_web_security_init();
1046 nd_web_api_init();
1047 mcp_initialize_subsystem();
1048 web_server_threading_selection();
1049
1050 delta_startup_time("web server sockets");
1051 if(web_server_mode != WEB_SERVER_MODE_NONE)
1052 web_server_listen_sockets_setup();
1053
1054 // ----------------------------------------------------------------------------------------------------------------
1055 delta_startup_time("sqlite");
1056
1057 if (sqlite_library_init())
1058 fatal("Failed to initialize sqlite library");
1059
1060 // ----------------------------------------------------------------------------------------------------------------
1061 delta_startup_time("ML");
1062
1063 ml_init();
1064
1065 // ----------------------------------------------------------------------------------------------------------------
1066 delta_startup_time("resource limits");
1067
1068 #ifdef NETDATA_INTERNAL_CHECKS
1069 if(debug_flags != 0) {
1070 struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
1071 if(setrlimit(RLIMIT_CORE, &rl) != 0)
1072 netdata_log_error("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
1073 #ifdef HAVE_SYS_PRCTL_H
1074 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
1075 #endif
1076 }
1077 #endif /* NETDATA_INTERNAL_CHECKS */
1078
1079 set_nofile_limit(&rlimit_nofile);
1080
1081 // ----------------------------------------------------------------------------------------------------------------
1082 delta_startup_time("stop temporary spawn server");
1083 // stop the old server and later start a new one under the new permissions
1084 netdata_main_spawn_server_cleanup();
1085
1086 // ----------------------------------------------------------------------------------------------------------------
1087
1088 #if defined(OS_LINUX) || defined(OS_MACOS) || defined(OS_FREEBSD)
1089 delta_startup_time("become daemon");
1090
1091 // fork, switch user, create the pid file, set process priority
1092 if(become_daemon(dont_fork, user) == -1)
1093 fatal("Cannot daemonize myself.");
1094 #else
1095 (void)dont_fork;
1096 #endif
1097
1098 // ----------------------------------------------------------------------------------------------------------------
1099 delta_startup_time("plugins spawn server");
1100
1101 netdata_main_spawn_server_init("plugins", argc, (const char **)argv);
1102
1103 #ifdef ENABLE_SENTRY
1104 // ----------------------------------------------------------------------------------------------------------------
1105 delta_startup_time("sentry");
1106
1107 nd_sentry_init();
1108 #endif
1109
1110 // ----------------------------------------------------------------------------------------------------------------
1111 delta_startup_time("home");
1112
1113 // The "HOME" env var points to the root's home dir because Netdata starts as root. Can't use "HOME".
1114 struct passwd *pw = getpwuid(getuid());
1115 if (inicfg_exists(&netdata_config, CONFIG_SECTION_DIRECTORIES, "home") || !pw || !pw->pw_dir) {
1116 netdata_configured_home_dir = inicfg_get_path(&netdata_config, CONFIG_SECTION_DIRECTORIES, "home", netdata_configured_home_dir);
1117 }
1118 else
1119 netdata_configured_home_dir = inicfg_get_path(&netdata_config, CONFIG_SECTION_DIRECTORIES, "home", pw->pw_dir);
1120
1121 nd_setenv("HOME", netdata_configured_home_dir, 1);
1122
1123 // ----------------------------------------------------------------------------------------------------------------
1124 delta_startup_time("dyncfg");
1125
1126 dyncfg_init(true);
1127
1128 // ----------------------------------------------------------------------------------------------------------------
1129 delta_startup_time("threads after fork");
1130
1131 netdata_conf_reset_stack_size();
1132
1133 // ----------------------------------------------------------------------------------------------------------------
1134 delta_startup_time("registry");
1135
1136 registry_load();
1137 cloud_conf_init_after_registry();
1138 netdata_random_session_id_generate();
1139
1140 #ifdef ENABLE_SENTRY
1141 nd_sentry_set_user(machine_guid_get_txt());
1142 #endif
1143
1144 // ----------------------------------------------------------------------------------------------------------------
1145 delta_startup_time("system info");
1146
1147 struct rrdhost_system_info *system_info = rrdhost_system_info_create();
1148 rrdhost_system_info_detect(system_info);
1149
1150 get_install_type(system_info);
1151
1152 set_late_analytics_variables(system_info);
1153
1154 // ----------------------------------------------------------------------------------------------------------------
1155 delta_startup_time("RRD structures");
1156
1157 delta_startup_time("commands liveness support");
1158
1159 commands_init();
1160
1161 abort_on_fatal_disable();
1162 if (rrd_init(netdata_configured_hostname, system_info, false))
1163 fatal("Cannot initialize localhost instance with name '%s'.", netdata_configured_hostname);
1164
1165 abort_on_fatal_enable();
1166 system_info = NULL; // system_info is now freed by rrd_init
1167
1168 // ----------------------------------------------------------------------------------------------------------------
1169 delta_startup_time("localhost labels");
1170
1171 reload_host_labels();
1172
1173 // ----------------------------------------------------------------------------------------------------------------
1174 delta_startup_time("saved bearer tokens");
1175
1176 bearer_tokens_init();
1177
1178 // ----------------------------------------------------------------------------------------------------------------
1179 delta_startup_time("claiming info");
1180
1181 load_claiming_state();
1182
1183 // ----------------------------------------------------------------------------------------------------------------
1184 delta_startup_time("static threads");
1185
1186 nd_log_limits_reset();
1187 get_agent_event_time_median_init();
1188
1189 netdata_conf_section_web();
1190
1191 for (i = 0; static_threads[i].name != NULL ; i++) {
1192 struct netdata_static_thread *st = &static_threads[i];
1193
1194 if(st->enabled) {
1195 netdata_log_debug(D_SYSTEM, "Starting thread %s.", st->name);
1196 st->thread = nd_thread_create(st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, st);
1197 }
1198 else
1199 netdata_log_debug(D_SYSTEM, "Not starting thread %s.", st->name);
1200 }
1201 ml_start_threads();
1202
1203 // ----------------------------------------------------------------------------------------------------------------
1204 delta_startup_time("commands full API");
1205
1206 commands_init();
1207
1208 // ----------------------------------------------------------------------------------------------------------------
1209 delta_startup_time("agent start timings");
1210
1211 usec_t ready_ut = now_monotonic_usec();
1212 add_agent_event(EVENT_AGENT_START_TIME, (int64_t ) (ready_ut - started_ut));
1213 usec_t median_start_time = get_agent_event_time_median(EVENT_AGENT_START_TIME);
1214 netdata_log_info(
1215 "NETDATA STARTUP: version '%s', sqlite '%s', completed in %llu ms (median start up time is %llu ms). "
1216 "Enjoy X-Ray Vision for your infrastructure!",
1217 NETDATA_VERSION, sqlite3_libversion(),
1218 (ready_ut - started_ut) / USEC_PER_MS, median_start_time / USEC_PER_MS);
1219
1220 cleanup_agent_event_log();
1221 netdata_ready_store(true);
1222
1223 // ----------------------------------------------------------------------------------------------------------------
1224
1225 {
1226 if(analytics_check_enabled())
1227 delta_startup_time("anonymous analytics");
1228 else // collect data but do not send it (needed in /api/v1/info)
1229 delta_startup_time("anonymous analytics (disabled)");
1230
1231 // check if ANALYTICS needs to start
1232 for (i = 0; static_threads[i].name != NULL; i++) {
1233 if (!strncmp(static_threads[i].name, "ANALYTICS", 9)) {
1234 struct netdata_static_thread *st = &static_threads[i];
1235 st->enabled = 1;
1236 netdata_log_debug(D_SYSTEM, "Starting thread %s.", st->name);
1237 st->thread = nd_thread_create(st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, st);
1238 }
1239 }
1240 }
1241
1242 // ----------------------------------------------------------------------------------------------------------------
1243
1244 #ifdef HAVE_LIBDATACHANNEL
1245 delta_startup_time("webrtc");
1246 webrtc_initialize();
1247 #endif
1248
1249 // ----------------------------------------------------------------------------------------------------------------
1250 delta_startup_time("mrg cleanup");
1251
1252 #ifdef ENABLE_DBENGINE
1253 mrg_metric_prepopulate_cleanup(main_mrg);
1254 #endif
1255
1256 // ----------------------------------------------------------------------------------------------------------------
1257 delta_startup_time("done");
1258
1259 nd_log_register_fatal_final_cb(netdata_exit_fatal);
1260 daemon_status_file_startup_step(NULL);
1261 daemon_status_file_update_status(DAEMON_STATUS_RUNNING);
1262 return 10;
1263 }
1264
1265 #ifndef OS_WINDOWS
1266 int main(int argc, char *argv[])
1267 {
1268 int rc = netdata_main(argc, argv);
1269 if (rc != 10)
1270 return rc;
1271
1272 #if defined(FSANITIZE_ADDRESS)
1273 fprintf(stdout, "STDOUT: Sanitizers mode enabled...\n");
1274 fprintf(stderr, "STDERR: Sanitizers mode enabled...\n");
1275 #endif
1276
1277 nd_process_signals();
1278 return 1;
1279 }
1280 #endif