Same as 'update every' config file option.", "seconds", "1"},
{'u', "System username to run as.", "username", "netdata"},
{'v', "Version of the program", NULL, NULL},
- {'W', "vendor options.", "stacksize=<size>|unittest|debug_flag", NULL},
+ {'W', "vendor options.", "stacksize=N|unittest|debug_flags=N", NULL},
};
void help(int exitcode) {
} while(argv[i][0] != '-' && opt_index >= *argc);
}
+static const char *verify_required_directory(const char *dir) {
+ if(chdir(dir) == -1)
+ fatal("Cannot cd to directory '%s'", dir);
+
+ DIR *d = opendir(dir);
+ if(!d)
+ fatal("Cannot examine the contents of directory '%s'", dir);
+ closedir(d);
+
+ return dir;
+}
int main(int argc, char **argv)
{
+ char *hostname = "localhost";
int i, check_config = 0;
int config_loaded = 0;
int dont_fork = 0;
size_t wanted_stacksize = 0, stacksize = 0;
pthread_attr_t attr;
- // global initialization
- get_HZ();
-
// set the name for logging
program_name = "netdata";
- // parse command line.
-
// parse depercated options
// TODO: Remove this block with the next major release.
{
break;
case 'v':
// TODO: Outsource version to makefile which can compute version from git.
- printf("netdata 1.2.1_master\n");
+ printf("netdata %s\n", VERSION);
return 0;
case 'W':
{
}
}
- if(!config_loaded) load_config(NULL, 0);
+ if(!config_loaded)
+ load_config(NULL, 0);
+
+ {
+ char *pmax = config_get("global", "glibc malloc arena max for plugins", "1");
+ if(pmax && *pmax)
+ setenv("MALLOC_ARENA_MAX", pmax, 1);
+
+#if defined(HAVE_C_MALLOPT)
+ int i = config_get_number("global", "glibc malloc arena max for netdata", 1);
+ if(i > 0)
+ mallopt(M_ARENA_MAX, 1);
+#endif
- // prepare configuration environment variables for the plugins
- setenv("NETDATA_CONFIG_DIR" , config_get("global", "config directory" , CONFIG_DIR) , 1);
- setenv("NETDATA_PLUGINS_DIR", config_get("global", "plugins directory" , PLUGINS_DIR), 1);
- setenv("NETDATA_WEB_DIR" , config_get("global", "web files directory", WEB_DIR) , 1);
- setenv("NETDATA_CACHE_DIR" , config_get("global", "cache directory" , CACHE_DIR) , 1);
- setenv("NETDATA_LIB_DIR" , config_get("global", "lib directory" , VARLIB_DIR) , 1);
- setenv("NETDATA_LOG_DIR" , config_get("global", "log directory" , LOG_DIR) , 1);
- setenv("NETDATA_HOST_PREFIX", config_get("global", "host access prefix" , "") , 1);
- setenv("HOME" , config_get("global", "home directory" , CACHE_DIR) , 1);
+ char *config_dir = config_get("global", "config directory", CONFIG_DIR);
- // disable buffering for python plugins
- setenv("PYTHONUNBUFFERED", "1", 1);
+ // prepare configuration environment variables for the plugins
+ setenv("NETDATA_CONFIG_DIR" , verify_required_directory(config_dir) , 1);
+ setenv("NETDATA_PLUGINS_DIR", verify_required_directory(config_get("global", "plugins directory" , PLUGINS_DIR)), 1);
+ setenv("NETDATA_WEB_DIR" , verify_required_directory(config_get("global", "web files directory", WEB_DIR)) , 1);
+ setenv("NETDATA_CACHE_DIR" , verify_required_directory(config_get("global", "cache directory" , CACHE_DIR)) , 1);
+ setenv("NETDATA_LIB_DIR" , verify_required_directory(config_get("global", "lib directory" , VARLIB_DIR)) , 1);
+ setenv("NETDATA_LOG_DIR" , verify_required_directory(config_get("global", "log directory" , LOG_DIR)) , 1);
- // avoid flood calls to stat(/etc/localtime)
- // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux
- setenv("TZ", ":/etc/localtime", 0);
+ setenv("NETDATA_HOST_PREFIX", config_get("global", "host access prefix" , "") , 1);
+ setenv("HOME" , config_get("global", "home directory" , CACHE_DIR) , 1);
+
+ // disable buffering for python plugins
+ setenv("PYTHONUNBUFFERED", "1", 1);
+
+ // avoid flood calls to stat(/etc/localtime)
+ // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux
+ setenv("TZ", ":/etc/localtime", 0);
+
+ // work while we are cd into config_dir
+ // to allow the plugins refer to their config
+ // files using relative filenames
+ if(chdir(config_dir) == -1)
+ fatal("Cannot cd to '%s'", config_dir);
- {
char path[1024 + 1], *p = getenv("PATH");
if(!p) p = "/bin:/usr/bin";
snprintfz(path, 1024, "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin");
setenv("PATH", config_get("plugins", "PATH environment variable", path), 1);
}
- // cd to /tmp to avoid any plugins writing files at random places
- if(chdir("/tmp")) error("netdata: ERROR: Cannot cd to /tmp");
-
char *user = NULL;
{
char *flags = config_get("global", "debug flags", "0x00000000");
global_host_prefix = config_get("global", "host access prefix", "");
setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1);
+ get_system_HZ();
+ get_system_cpus();
+ get_system_pid_max();
+
// --------------------------------------------------------------------
stdout_filename = config_get("global", "debug log", LOG_DIR "/debug.log");
stderr_filename = config_get("global", "error log", LOG_DIR "/error.log");
stdaccess_filename = config_get("global", "access log", LOG_DIR "/access.log");
- error_log_throttle_period = config_get_number("global", "errors flood protection period", error_log_throttle_period);
+ error_log_throttle_period_backup =
+ error_log_throttle_period = config_get_number("global", "errors flood protection period", error_log_throttle_period);
setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get("global", "errors flood protection period" , ""), 1);
error_log_errors_per_period = (unsigned long)config_get_number("global", "errors to trigger flood protection", error_log_errors_per_period);
error_log_throttle_period = 0;
error_log_errors_per_period = 0;
}
+ error_log_limit_unlimited();
// --------------------------------------------------------------------
error("WARNING: Cannot get machine hostname.");
hostname = config_get("global", "hostname", hostnamebuf);
debug(D_OPTIONS, "hostname set to '%s'", hostname);
+ setenv("NETDATA_HOSTNAME", hostname, 1);
}
// --------------------------------------------------------------------
// this causes the threads to block signals.
sigset_t sigset;
sigfillset(&sigset);
-
- if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) == -1) {
+ if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) == -1)
error("Could not block signals for threads");
- }
// Catch signals which we want to use
struct sigaction sa;
- sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGINT);
- sigaddset(&sa.sa_mask, SIGTERM);
- sa.sa_handler = sig_handler_exit;
sa.sa_flags = 0;
- if(sigaction(SIGINT, &sa, NULL) == -1) {
+
+ // ingore all signals while we run in a signal handler
+ sigfillset(&sa.sa_mask);
+
+ // INFO: If we add signals here we have to unblock them
+ // at popen.c when running a external plugin.
+
+ // Ignore SIGPIPE completely.
+ sa.sa_handler = SIG_IGN;
+ if(sigaction(SIGPIPE, &sa, NULL) == -1)
+ error("Failed to change signal handler for SIGPIPE");
+
+ sa.sa_handler = sig_handler_exit;
+ if(sigaction(SIGINT, &sa, NULL) == -1)
error("Failed to change signal handler for SIGINT");
- }
- if(sigaction(SIGTERM, &sa, NULL) == -1) {
+
+ sa.sa_handler = sig_handler_exit;
+ if(sigaction(SIGTERM, &sa, NULL) == -1)
error("Failed to change signal handler for SIGTERM");
- }
- sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGHUP);
sa.sa_handler = sig_handler_logrotate;
- sa.sa_flags = 0;
- if(sigaction(SIGHUP, &sa, NULL) == -1) {
+ if(sigaction(SIGHUP, &sa, NULL) == -1)
error("Failed to change signal handler for SIGHUP");
- }
// save database on SIGUSR1
- sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGUSR1);
sa.sa_handler = sig_handler_save;
- if(sigaction(SIGUSR1, &sa, NULL) == -1) {
+ if(sigaction(SIGUSR1, &sa, NULL) == -1)
error("Failed to change signal handler for SIGUSR1");
- }
- // Ignore SIGPIPE completely.
- // INFO: If we add signals here we have to unblock them
- // at popen.c when running a external plugin.
- sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGPIPE);
- sa.sa_handler = SIG_IGN;
- if(sigaction(SIGPIPE, &sa, NULL) == -1) {
- error("Failed to change signal handler for SIGPIPE");
- }
+ // reload health configuration on SIGUSR2
+ sa.sa_handler = sig_handler_reload_health;
+ if(sigaction(SIGUSR2, &sa, NULL) == -1)
+ error("Failed to change signal handler for SIGUSR2");
// --------------------------------------------------------------------
info("Successfully set pthread stacksize to %zu bytes", wanted_stacksize);
}
+ // ------------------------------------------------------------------------
+ // initialize rrd host
+
+ rrdhost_init(hostname);
+
// ------------------------------------------------------------------------
// initialize the registry
if(check_config)
exit(1);
+ // ------------------------------------------------------------------------
+ // enable log flood protection
+
+ error_log_limit_reset();
+
// ------------------------------------------------------------------------
// spawn the threads