]> arthur.barton.de Git - netdata.git/commitdiff
proper log file management; re-opening logs on SIGHUP; updated logrotate; updated...
authorCosta Tsaousis <costa@tsaousis.gr>
Fri, 12 Aug 2016 18:18:57 +0000 (21:18 +0300)
committerCosta Tsaousis <costa@tsaousis.gr>
Fri, 12 Aug 2016 18:18:57 +0000 (21:18 +0300)
src/daemon.c
src/daemon.h
src/log.c
src/log.h
src/main.c
system/netdata.logrotate.in
system/netdata.service.in

index 925abbf302a2bd082b3712408c1fd6371d08ec0a..5d24b6cabe39ab7951b9c683d45eda7c5b8b083d 100644 (file)
@@ -5,22 +5,32 @@ char pidfile[FILENAME_MAX + 1] = "";
 
 void sig_handler_exit(int signo)
 {
-       if(signo) {
-               error_log_limit_unlimited();
-               error("Received signal %d. Exiting...", signo);
-               netdata_exit = 1;
-       }
+    if(signo) {
+        error_log_limit_unlimited();
+        error("Received signal %d. Exiting...", signo);
+        netdata_exit = 1;
+    }
+}
+
+void sig_handler_logrotate(int signo)
+{
+    if(signo) {
+        error_log_limit_reset();
+        info("Received signal %d to re-open the log files", signo);
+        reopen_all_log_files();
+    }
 }
 
 void sig_handler_save(int signo)
 {
        if(signo) {
+        error_log_limit_reset();
                info("Received signal %d to save the database...", signo);
                rrdset_save_all();
        }
 }
 
-static void properly_chown_netdata_generated_file(int fd, uid_t uid, gid_t gid) {
+static void chown_open_file(int fd, uid_t uid, gid_t gid) {
        if(fd == -1) return;
 
        struct stat buf;
@@ -36,7 +46,7 @@ static void properly_chown_netdata_generated_file(int fd, uid_t uid, gid_t gid)
        }
 }
 
-int become_user(const char *username, int access_fd, int output_fd, int error_fd, int pid_fd)
+int become_user(const char *username, int pid_fd)
 {
        struct passwd *pw = getpwnam(username);
        if(!pw) {
@@ -59,10 +69,10 @@ int become_user(const char *username, int access_fd, int output_fd, int error_fd
                }
        }
 
-       properly_chown_netdata_generated_file(access_fd, uid, gid);
-       properly_chown_netdata_generated_file(output_fd, uid, gid);
-       properly_chown_netdata_generated_file(error_fd, uid, gid);
-       properly_chown_netdata_generated_file(pid_fd, uid, gid);
+       chown_open_file(STDOUT_FILENO, uid, gid);
+       chown_open_file(STDERR_FILENO, uid, gid);
+       chown_open_file(stdaccess_fd, uid, gid);
+       chown_open_file(pid_fd, uid, gid);
 
        if(supplementary_groups && ngroups) {
                if(setgroups(ngroups, supplementary_groups) == -1)
@@ -133,81 +143,8 @@ int sched_setscheduler_idle(void) {
        return i;
 }
 
-int become_daemon(int dont_fork, int close_all_files, const char *user, const char *input, const char *output, const char *error, const char *access, int *access_fd, FILE **access_fp)
+int become_daemon(int dont_fork, const char *user)
 {
-       fflush(NULL);
-
-       // open the files before forking
-       int input_fd = -1, output_fd = -1, error_fd = -1, dev_null;
-
-       if(input && *input) {
-               if((input_fd = open(input, O_RDONLY, 0666)) == -1) {
-                       error("Cannot open input file '%s'.", input);
-                       return -1;
-               }
-       }
-
-       if(output && *output && strcmp(output, "/dev/null") != 0) {
-               if((output_fd = open(output, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
-                       error("Cannot open output log file '%s'", output);
-                       if(input_fd != -1) close(input_fd);
-                       return -1;
-               }
-       }
-
-       if(error && *error && strcmp(error, "/dev/null") != 0) {
-               if((error_fd = open(error, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
-                       error("Cannot open error log file '%s'.", error);
-                       if(input_fd != -1) close(input_fd);
-                       if(output_fd != -1) close(output_fd);
-                       return -1;
-               }
-       }
-
-       if(access && *access && access_fd && strcmp(access, "/dev/null") != 0) {
-               if((*access_fd = open(access, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
-                       error("Cannot open access log file '%s'", access);
-                       if(input_fd != -1) close(input_fd);
-                       if(output_fd != -1) close(output_fd);
-                       if(error_fd != -1) close(error_fd);
-                       return -1;
-               }
-
-               if(access_fp) {
-                       *access_fp = fdopen(*access_fd, "w");
-                       if(!*access_fp) {
-                               error("Cannot migrate file's '%s' fd %d.", access, *access_fd);
-                               if(input_fd != -1) close(input_fd);
-                               if(output_fd != -1) close(output_fd);
-                               if(error_fd != -1) close(error_fd);
-                               close(*access_fd);
-                               *access_fd = -1;
-                               return -1;
-                       }
-                       if(setvbuf(*access_fp, NULL, _IOLBF, 0) != 0)
-                               error("Cannot set line buffering on access.log");
-               }
-       }
-
-       if((dev_null = open("/dev/null", O_RDWR, 0666)) == -1) {
-               perror("Cannot open /dev/null");
-               if(input_fd != -1) close(input_fd);
-               if(output_fd != -1) close(output_fd);
-               if(error_fd != -1) close(error_fd);
-               if(access && access_fd && *access_fd != -1) {
-                       close(*access_fd);
-                       *access_fd = -1;
-                       if(access_fp) {
-                               fclose(*access_fp);
-                               *access_fp = NULL;
-                       }
-               }
-               return -1;
-       }
-
-       // all files opened
-       // lets do it
-
        if(!dont_fork) {
                int i = fork();
                if(i == -1) {
@@ -235,70 +172,10 @@ int become_daemon(int dont_fork, int close_all_files, const char *user, const ch
                }
        }
 
-       // close all files
-       if(close_all_files) {
-               int i;
-               for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--)
-                       if(
-                               ((access_fd && i != *access_fd) || !access_fd)
-                               && i != dev_null
-                               && i != input_fd
-                               && i != output_fd
-                               && i != error_fd
-                               && fd_is_valid(i)
-                               ) close(i);
-       }
-       else {
-               close(STDIN_FILENO);
-               close(STDOUT_FILENO);
-               close(STDERR_FILENO);
-       }
-
-       // put the opened files
-       // to our standard file descriptors
-       if(input_fd != -1) {
-               if(input_fd != STDIN_FILENO) {
-                       dup2(input_fd, STDIN_FILENO);
-                       close(input_fd);
-               }
-               input_fd = -1;
-       }
-       else dup2(dev_null, STDIN_FILENO);
-
-       if(output_fd != -1) {
-               if(output_fd != STDOUT_FILENO) {
-                       dup2(output_fd, STDOUT_FILENO);
-                       close(output_fd);
-               }
-
-               if(setvbuf(stdout, NULL, _IOLBF, 0) != 0)
-                       error("Cannot set line buffering on debug.log");
-
-               output_fd = STDOUT_FILENO;
-       }
-       else dup2(dev_null, STDOUT_FILENO);
-
-       if(error_fd != -1) {
-               if(error_fd != STDERR_FILENO) {
-                       dup2(error_fd, STDERR_FILENO);
-                       close(error_fd);
-               }
-
-               if(setvbuf(stderr, NULL, _IOLBF, 0) != 0)
-                       error("Cannot set line buffering on error.log");
-
-               error_fd = STDERR_FILENO;
-       }
-       else dup2(dev_null, STDERR_FILENO);
-
-       // close /dev/null
-       if(dev_null != STDIN_FILENO && dev_null != STDOUT_FILENO && dev_null != STDERR_FILENO)
-               close(dev_null);
-
        // generate our pid file
        int pidfd = -1;
        if(pidfile[0]) {
-               pidfd = open(pidfile, O_RDWR | O_CREAT, 0644);
+               pidfd = open(pidfile, O_WRONLY | O_CREAT, 0644);
                if(pidfd >= 0) {
                        if(ftruncate(pidfd, 0) != 0)
                                error("Cannot truncate pidfile '%s'.", pidfile);
@@ -325,7 +202,7 @@ int become_daemon(int dont_fork, int close_all_files, const char *user, const ch
        }
 
        if(user && *user) {
-               if(become_user(user, (access_fd)?*access_fd:-1, output_fd, error_fd, pidfd) != 0) {
+               if(become_user(user, pidfd) != 0) {
                        error("Cannot become user '%s'. Continuing as we are.", user);
                }
                else info("Successfully became user '%s'.", user);
index 8d62469b65a1b611db8da530407f56a466ecf3cb..6cf1b871972d3db201f2523906e1070ec023ff06 100644 (file)
@@ -3,10 +3,11 @@
 
 extern void sig_handler_exit(int signo);
 extern void sig_handler_save(int signo);
+extern void sig_handler_logrotate(int signo);
 
-extern int become_user(const char *username, int access_fd, int output_fd, int error_fd, int pid_fd);
+extern int become_user(const char *username, int pid_fd);
 
-extern int become_daemon(int dont_fork, int close_all_files, const char *user, const char *input, const char *output, const char *error, const char *access, int *access_fd, FILE **access_fp);
+extern int become_daemon(int dont_fork, const char *user);
 
 extern void netdata_cleanup_and_exit(int i);
 
index aa0f1b21168f28f967348daf7e5b59a03b8b26f2..1cbc6f9c0362d23e139578eafc98935fabe9901f 100644 (file)
--- a/src/log.c
+++ b/src/log.c
 #include "common.h"
 
-// ----------------------------------------------------------------------------
-// LOG
-
 const char *program_name = "";
 unsigned long long debug_flags = DEBUG;
 
-int silent = 0;
-
-int access_fd = -1;
-FILE *stdaccess = NULL;
-
 int access_log_syslog = 1;
 int error_log_syslog = 1;
 int output_log_syslog = 1;     // debug log
 
+int stdaccess_fd = -1;
+FILE *stdaccess = NULL;
+
+const char *stdaccess_filename = NULL;
+const char *stderr_filename = NULL;
+const char *stdout_filename = NULL;
+
+void syslog_init(void) {
+    static int i = 0;
+
+    if(!i) {
+        openlog(program_name, LOG_PID, LOG_DAEMON);
+        i = 1;
+    }
+}
+
+int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) {
+    int f, t;
+
+    if(!filename || !*filename || !strcmp(filename, "none"))
+        filename = "/dev/null";
+
+    if(!strcmp(filename, "syslog")) {
+        filename = "/dev/null";
+        syslog_init();
+        if(enabled_syslog) *enabled_syslog = 1;
+    }
+    else if(enabled_syslog) *enabled_syslog = 0;
+
+    // don't do anything if the user is willing
+    // to have the standard one
+    if(!strcmp(filename, "system"))
+        return fd;
+
+    if(!strcmp(filename, "stdout"))
+        f = STDOUT_FILENO;
+
+    else if(!strcmp(filename, "stderr"))
+        f = STDERR_FILENO;
+
+    else {
+        f = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0664);
+        if(f == -1) {
+            error("Cannot open file '%s'. Leaving %d to its default.", filename, fd);
+            return fd;
+        }
+    }
+
+    // if there is a level-2 file pointer
+    // flush it before switching the level-1 fds
+    if(fp && *fp)
+        fflush(*fp);
+
+    if(fd != f && fd != -1) {
+        // it automatically closes
+        t = dup2(f, fd);
+        if (t == -1) {
+            error("Cannot dup2() new fd %d to old fd %d for '%s'", f, fd, filename);
+            close(f);
+            return fd;
+        }
+        // info("dup2() new fd %d to old fd %d for '%s'", f, fd, filename);
+        close(f);
+    }
+    else fd = f;
+
+    if(fp && *fp == NULL) {
+        // info("fdopen(%d) on filename '%s'", fd, filename);
+
+        FILE *n = fdopen(fd, "a");
+        if (!n)
+            error("Cannot fdopen() fd %d ('%s')", fd, filename);
+
+        else {
+            if (setvbuf(n, NULL, _IOLBF, 0) != 0)
+                error("Cannot set line buffering on fd %d ('%s')", fd, filename);
+
+            if(!*fp)
+                *fp = n;
+            else {
+                FILE *o = *fp;
+                *fp = n;
+                fclose(o);
+            }
+        }
+    }
+
+    return fd;
+}
+
+void reopen_all_log_files() {
+    if(stdout_filename)
+        open_log_file(STDOUT_FILENO, &stdout, stdout_filename, &output_log_syslog);
+
+    if(stderr_filename)
+        open_log_file(STDERR_FILENO, &stderr, stderr_filename, &error_log_syslog);
+
+    if(stdaccess_filename)
+        stdaccess_fd = open_log_file(stdaccess_fd, &stdaccess, stdaccess_filename, &access_log_syslog);
+}
+
+void open_all_log_files() {
+    // disable stdin
+    open_log_file(STDIN_FILENO, &stdin, "/dev/null", NULL);
+
+    open_log_file(STDOUT_FILENO, &stdout, stdout_filename, &output_log_syslog);
+    open_log_file(STDERR_FILENO, &stderr, stderr_filename, &error_log_syslog);
+    stdaccess_fd = open_log_file(stdaccess_fd, &stdaccess, stdaccess_filename, &access_log_syslog);
+}
+
+// ----------------------------------------------------------------------------
+// error log throttling
+
 time_t error_log_throttle_period = 1200;
 unsigned long error_log_errors_per_period = 200;
 
@@ -94,6 +199,13 @@ int error_log_limit(int reset) {
        return 0;
 }
 
+// ----------------------------------------------------------------------------
+// print the date
+
+// FIXME
+// this should print the date in a buffer the way it
+// is now, logs from multiple threads may be multiplexed
+
 void log_date(FILE *out)
 {
                char outstr[24];
@@ -109,6 +221,9 @@ void log_date(FILE *out)
                fprintf(out, "%s: ", outstr);
 }
 
+// ----------------------------------------------------------------------------
+// debug log
+
 void debug_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
 {
        va_list args;
@@ -129,6 +244,9 @@ void debug_int( const char *file, const char *function, const unsigned long line
        fflush(stdout);
 }
 
+// ----------------------------------------------------------------------------
+// info log
+
 void info_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
 {
        va_list args;
@@ -153,6 +271,9 @@ void info_int( const char *file, const char *function, const unsigned long line,
        }
 }
 
+// ----------------------------------------------------------------------------
+// error log
+
 void error_int( const char *prefix, const char *file, const char *function, const unsigned long line, const char *fmt, ... )
 {
        va_list args;
@@ -207,6 +328,9 @@ void fatal_int( const char *file, const char *function, const unsigned long line
        netdata_cleanup_and_exit(1);
 }
 
+// ----------------------------------------------------------------------------
+// access log
+
 void log_access( const char *fmt, ... )
 {
        va_list args;
index 95b6b301ed7a9496d4d0c1bfa89fbe634b152353..576f5ee7cd3bde9b524c576256d85ba08c3bc142 100644 (file)
--- a/src/log.h
+++ b/src/log.h
@@ -33,11 +33,13 @@ extern unsigned long long debug_flags;
 
 extern const char *program_name;
 
-extern int silent;
-
-extern int access_fd;
+extern int stdaccess_fd;
 extern FILE *stdaccess;
 
+extern const char *stdaccess_filename;
+extern const char *stderr_filename;
+extern const char *stdout_filename;
+
 extern int access_log_syslog;
 extern int error_log_syslog;
 extern int output_log_syslog;
@@ -46,10 +48,13 @@ extern time_t error_log_throttle_period;
 extern unsigned long error_log_errors_per_period;
 extern int error_log_limit(int reset);
 
+extern void open_all_log_files();
+extern void reopen_all_log_files();
+
 #define error_log_limit_reset() do { error_log_limit(1); } while(0)
 #define error_log_limit_unlimited() do { error_log_throttle_period = 0; } while(0)
 
-#define debug(type, args...) do { if(unlikely(!silent && (debug_flags & type))) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args); } while(0)
+#define debug(type, args...) do { if(unlikely(debug_flags & type)) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args); } while(0)
 #define info(args...)    info_int(__FILE__, __FUNCTION__, __LINE__, ##args)
 #define infoerr(args...) error_int("INFO", __FILE__, __FUNCTION__, __LINE__, ##args)
 #define error(args...)   error_int("ERROR", __FILE__, __FUNCTION__, __LINE__, ##args)
index 2065b506a845a7e3cea999860f66fd321f54e52a..4ea6619f8c0f943f1d1443fa221dbe6ce96cafc2 100644 (file)
@@ -420,10 +420,6 @@ int main(int argc, char **argv)
        // cd to /tmp to avoid any plugins writing files at random places
        if(chdir("/tmp")) error("netdata: ERROR: Cannot cd to /tmp");
 
-       char *input_log_file = NULL;
-       char *output_log_file = NULL;
-       char *error_log_file = NULL;
-       char *access_log_file = NULL;
        char *user = NULL;
        {
                char *flags = config_get("global", "debug flags",  "0x00000000");
@@ -449,36 +445,14 @@ int main(int argc, char **argv)
 
                // --------------------------------------------------------------------
 
-
                global_host_prefix = config_get("global", "host access prefix", "");
                setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1);
 
                // --------------------------------------------------------------------
 
-               output_log_file = config_get("global", "debug log", LOG_DIR "/debug.log");
-               if(strcmp(output_log_file, "syslog") == 0) {
-                       output_log_syslog = 1;
-                       output_log_file = NULL;
-               }
-               else if(strcmp(output_log_file, "none") == 0) {
-                       output_log_syslog = 0;
-                       output_log_file = NULL;
-               }
-               else output_log_syslog = 0;
-
-               // --------------------------------------------------------------------
-
-               error_log_file = config_get("global", "error log", LOG_DIR "/error.log");
-               if(strcmp(error_log_file, "syslog") == 0) {
-                       error_log_syslog = 1;
-                       error_log_file = NULL;
-               }
-               else if(strcmp(error_log_file, "none") == 0) {
-                       error_log_syslog = 0;
-                       error_log_file = NULL;
-                       // optimization - do not even generate debug log entries
-               }
-               else error_log_syslog = 0;
+               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);
                setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get("global", "errors flood protection period"    , ""), 1);
@@ -488,19 +462,6 @@ int main(int argc, char **argv)
 
                // --------------------------------------------------------------------
 
-               access_log_file = config_get("global", "access log", LOG_DIR "/access.log");
-               if(strcmp(access_log_file, "syslog") == 0) {
-                       access_log_syslog = 1;
-                       access_log_file = NULL;
-               }
-               else if(strcmp(access_log_file, "none") == 0) {
-                       access_log_syslog = 0;
-                       access_log_file = NULL;
-               }
-               else access_log_syslog = 0;
-
-               // --------------------------------------------------------------------
-
                rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode)));
 
                // --------------------------------------------------------------------
@@ -551,17 +512,13 @@ int main(int argc, char **argv)
                        error("Could not block signals for threads");
                }
 
-               // Catch signals which we want to use to quit savely
+               // Catch signals which we want to use
                struct sigaction sa;
                sigemptyset(&sa.sa_mask);
-               sigaddset(&sa.sa_mask, SIGHUP);
                sigaddset(&sa.sa_mask, SIGINT);
                sigaddset(&sa.sa_mask, SIGTERM);
                sa.sa_handler = sig_handler_exit;
                sa.sa_flags = 0;
-               if(sigaction(SIGHUP, &sa, NULL) == -1) {
-                       error("Failed to change signal handler for SIGHUP");
-               }
                if(sigaction(SIGINT, &sa, NULL) == -1) {
                        error("Failed to change signal handler for SIGINT");
                }
@@ -569,7 +526,17 @@ int main(int argc, char **argv)
                        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) {
+            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) {
                        error("Failed to change signal handler for SIGUSR1");
@@ -578,6 +545,8 @@ int main(int argc, char **argv)
                // 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");
@@ -621,7 +590,11 @@ int main(int argc, char **argv)
                create_listen_sockets();
        }
 
-       if(become_daemon(dont_fork, 0, user, input_log_file, output_log_file, error_log_file, access_log_file, &access_fd, &stdaccess) == -1)
+    // initialize the log files
+    open_all_log_files();
+
+    // become daemon, switch user, create pid file, set process attributes
+    if(become_daemon(dont_fork, user) == -1)
                fatal("Cannot demonize myself.");
 
 #ifdef NETDATA_INTERNAL_CHECKS
@@ -633,9 +606,6 @@ int main(int argc, char **argv)
        }
 #endif /* NETDATA_INTERNAL_CHECKS */
 
-       if(output_log_syslog || error_log_syslog || access_log_syslog)
-               openlog("netdata", LOG_PID, LOG_DAEMON);
-
        info("NetData started on pid %d", getpid());
 
 
index d06944610adc312974f5927b033bedd6cdc1fc64..7858ef0dc5055ad71fd94d0c6e1dab0257098955 100644 (file)
@@ -6,14 +6,8 @@
        delaycompress
        notifempty
        sharedscripts
-       #
-       # if you add netdata to your init.d/system.d
-       # comment su & copytruncate and uncomment postrotate
-       # to have netdata restart when logs are rotated
-       create 0640 netdata netdata
-       copytruncate
-       #
-       #postrotate
-       #       /sbin/service netdata try-restart >/dev/null
-       #endscript
+       create 0664 netdata netdata
+       postrotate
+               /sbin/killall -HUP netdata
+       endscript
 }
index 0dd6eba38d9f18aa4f3d8ee922a3b00390c2e495..afdf0d78ce3c24422bd116c1f650ba32e47b8383 100644 (file)
@@ -1,27 +1,44 @@
 [Unit]
-Description=Linux real time system monitoring, done right
+Description=Real time performance monitoring
 After=network.target httpd.service squid.service nfs-server.service mysqld.service named.service postfix.service
 
 [Service]
-Type=forking
+Type=simple
 WorkingDirectory=/tmp
 User=netdata
 Group=netdata
 RuntimeDirectory=netdata
-PIDFile=@localstatedir_POST@/run/netdata/netdata.pid
-ExecStart=@sbindir_POST@/netdata -P @localstatedir_POST@/run/netdata/netdata.pid
+ExecStartPre=/bin/mkdir -p @localstatedir_POST@/run/netdata
+ExecStartPre=/bin/chown -R netdata:netdata @localstatedir_POST@/run/netdata
+ExecStartPre=/bin/chmod 0775 @localstatedir_POST@/run/netdata
+ExecStart=@sbindir_POST@/netdata -D -P @localstatedir_POST@/run/netdata/netdata.pid
+
+# -----------------------------------------------------------------------------
+# Stopping netdata
+
 KillMode=mixed
 KillSignal=SIGTERM
-TimeoutStopSec=30
 
-#Hardening
+# saving a big db on slow disks may need some time
+TimeoutStopSec=60
+
+# and disable SIGKILL - if sent during save, we will loose the db
+SendSIGKILL=no
+
+# -----------------------------------------------------------------------------
+# Hardening netdata
+
 AmbientCapabilities=CAP_DAC_READ_SEARCH CAP_SYS_PTRACE
 CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_SYS_PTRACE
 PrivateTmp=true
 ProtectSystem=full
 ProtectHome=read-only
-#NoNewPrivileges=true is implicitly set by the MemoryDenyWriteExecute=true
-MemoryDenyWriteExecute=true
+
+# is implicitly set by the MemoryDenyWriteExecute=true
+# NoNewPrivileges=true
+
+# Do not enable - it makes node.js plugins to crash
+# MemoryDenyWriteExecute=true
 
 [Install]
 WantedBy=multi-user.target