proper log file management; re-opening logs on SIGHUP; updated logrotate; updated systemd.service
Costa Tsaousis committed
Aug 12, 2016 at 21:18 UTC
7be4d1e56904c079e40a45b4e1ac85e5e940653a
7 files changed
+218
-230
src/daemon.c
+24
-147
@@ -5,22 +5,32 @@ char pidfile[FILENAME_MAX + 1] = "";
5
6
void sig_handler_exit(int signo)
7
{
8
- if(signo) {
9
- error_log_limit_unlimited();
10
- error("Received signal %d. Exiting...", signo);
11
- netdata_exit = 1;
12
- }
8
+ if(signo) {
9
+ error_log_limit_unlimited();
10
+ error("Received signal %d. Exiting...", signo);
11
+ netdata_exit = 1;
12
+ }
13
+}
14
+
15
+void sig_handler_logrotate(int signo)
16
+{
17
+ if(signo) {
18
+ error_log_limit_reset();
19
+ info("Received signal %d to re-open the log files", signo);
20
+ reopen_all_log_files();
21
+ }
22
}
23
24
void sig_handler_save(int signo)
25
{
26
if(signo) {
27
+ error_log_limit_reset();
28
info("Received signal %d to save the database...", signo);
29
rrdset_save_all();
30
}
31
}
32
23
-static void properly_chown_netdata_generated_file(int fd, uid_t uid, gid_t gid) {
33
+static void chown_open_file(int fd, uid_t uid, gid_t gid) {
34
if(fd == -1) return;
35
36
struct stat buf;
@@ -36,7 +46,7 @@ static void properly_chown_netdata_generated_file(int fd, uid_t uid, gid_t gid)
46
}
47
}
48
39
-int become_user(const char *username, int access_fd, int output_fd, int error_fd, int pid_fd)
49
+int become_user(const char *username, int pid_fd)
50
{
51
struct passwd *pw = getpwnam(username);
52
if(!pw) {
@@ -59,10 +69,10 @@ int become_user(const char *username, int access_fd, int output_fd, int error_fd
69
}
70
}
71
62
- properly_chown_netdata_generated_file(access_fd, uid, gid);
63
- properly_chown_netdata_generated_file(output_fd, uid, gid);
64
- properly_chown_netdata_generated_file(error_fd, uid, gid);
65
- properly_chown_netdata_generated_file(pid_fd, uid, gid);
72
+ chown_open_file(STDOUT_FILENO, uid, gid);
73
+ chown_open_file(STDERR_FILENO, uid, gid);
74
+ chown_open_file(stdaccess_fd, uid, gid);
75
+ chown_open_file(pid_fd, uid, gid);
76
77
if(supplementary_groups && ngroups) {
78
if(setgroups(ngroups, supplementary_groups) == -1)
@@ -133,81 +143,8 @@ int sched_setscheduler_idle(void) {
143
return i;
144
}
145
136
-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)
146
+int become_daemon(int dont_fork, const char *user)
147
{
138
- fflush(NULL);
139
-
140
- // open the files before forking
141
- int input_fd = -1, output_fd = -1, error_fd = -1, dev_null;
142
-
143
- if(input && *input) {
144
- if((input_fd = open(input, O_RDONLY, 0666)) == -1) {
145
- error("Cannot open input file '%s'.", input);
146
- return -1;
147
- }
148
- }
149
-
150
- if(output && *output && strcmp(output, "/dev/null") != 0) {
151
- if((output_fd = open(output, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
152
- error("Cannot open output log file '%s'", output);
153
- if(input_fd != -1) close(input_fd);
154
- return -1;
155
- }
156
- }
157
-
158
- if(error && *error && strcmp(error, "/dev/null") != 0) {
159
- if((error_fd = open(error, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
160
- error("Cannot open error log file '%s'.", error);
161
- if(input_fd != -1) close(input_fd);
162
- if(output_fd != -1) close(output_fd);
163
- return -1;
164
- }
165
- }
166
-
167
- if(access && *access && access_fd && strcmp(access, "/dev/null") != 0) {
168
- if((*access_fd = open(access, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
169
- error("Cannot open access log file '%s'", access);
170
- if(input_fd != -1) close(input_fd);
171
- if(output_fd != -1) close(output_fd);
172
- if(error_fd != -1) close(error_fd);
173
- return -1;
174
- }
175
-
176
- if(access_fp) {
177
- *access_fp = fdopen(*access_fd, "w");
178
- if(!*access_fp) {
179
- error("Cannot migrate file's '%s' fd %d.", access, *access_fd);
180
- if(input_fd != -1) close(input_fd);
181
- if(output_fd != -1) close(output_fd);
182
- if(error_fd != -1) close(error_fd);
183
- close(*access_fd);
184
- *access_fd = -1;
185
- return -1;
186
- }
187
- if(setvbuf(*access_fp, NULL, _IOLBF, 0) != 0)
188
- error("Cannot set line buffering on access.log");
189
- }
190
- }
191
-
192
- if((dev_null = open("/dev/null", O_RDWR, 0666)) == -1) {
193
- perror("Cannot open /dev/null");
194
- if(input_fd != -1) close(input_fd);
195
- if(output_fd != -1) close(output_fd);
196
- if(error_fd != -1) close(error_fd);
197
- if(access && access_fd && *access_fd != -1) {
198
- close(*access_fd);
199
- *access_fd = -1;
200
- if(access_fp) {
201
- fclose(*access_fp);
202
- *access_fp = NULL;
203
- }
204
- }
205
- return -1;
206
- }
207
-
208
- // all files opened
209
- // lets do it
210
-
148
if(!dont_fork) {
149
int i = fork();
150
if(i == -1) {
@@ -235,70 +172,10 @@ int become_daemon(int dont_fork, int close_all_files, const char *user, const ch
172
}
173
}
174
238
- // close all files
239
- if(close_all_files) {
240
- int i;
241
- for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--)
242
- if(
243
- ((access_fd && i != *access_fd) || !access_fd)
244
- && i != dev_null
245
- && i != input_fd
246
- && i != output_fd
247
- && i != error_fd
248
- && fd_is_valid(i)
249
- ) close(i);
250
- }
251
- else {
252
- close(STDIN_FILENO);
253
- close(STDOUT_FILENO);
254
- close(STDERR_FILENO);
255
- }
256
-
257
- // put the opened files
258
- // to our standard file descriptors
259
- if(input_fd != -1) {
260
- if(input_fd != STDIN_FILENO) {
261
- dup2(input_fd, STDIN_FILENO);
262
- close(input_fd);
263
- }
264
- input_fd = -1;
265
- }
266
- else dup2(dev_null, STDIN_FILENO);
267
-
268
- if(output_fd != -1) {
269
- if(output_fd != STDOUT_FILENO) {
270
- dup2(output_fd, STDOUT_FILENO);
271
- close(output_fd);
272
- }
273
-
274
- if(setvbuf(stdout, NULL, _IOLBF, 0) != 0)
275
- error("Cannot set line buffering on debug.log");
276
-
277
- output_fd = STDOUT_FILENO;
278
- }
279
- else dup2(dev_null, STDOUT_FILENO);
280
-
281
- if(error_fd != -1) {
282
- if(error_fd != STDERR_FILENO) {
283
- dup2(error_fd, STDERR_FILENO);
284
- close(error_fd);
285
- }
286
-
287
- if(setvbuf(stderr, NULL, _IOLBF, 0) != 0)
288
- error("Cannot set line buffering on error.log");
289
-
290
- error_fd = STDERR_FILENO;
291
- }
292
- else dup2(dev_null, STDERR_FILENO);
293
-
294
- // close /dev/null
295
- if(dev_null != STDIN_FILENO && dev_null != STDOUT_FILENO && dev_null != STDERR_FILENO)
296
- close(dev_null);
297
-
175
// generate our pid file
176
int pidfd = -1;
177
if(pidfile[0]) {
301
- pidfd = open(pidfile, O_RDWR | O_CREAT, 0644);
178
+ pidfd = open(pidfile, O_WRONLY | O_CREAT, 0644);
179
if(pidfd >= 0) {
180
if(ftruncate(pidfd, 0) != 0)
181
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
202
}
203
204
if(user && *user) {
328
- if(become_user(user, (access_fd)?*access_fd:-1, output_fd, error_fd, pidfd) != 0) {
205
+ if(become_user(user, pidfd) != 0) {
206
error("Cannot become user '%s'. Continuing as we are.", user);
207
}
208
else info("Successfully became user '%s'.", user);
src/daemon.h
+3
-2
@@ -3,10 +3,11 @@
3
4
extern void sig_handler_exit(int signo);
5
extern void sig_handler_save(int signo);
6
+extern void sig_handler_logrotate(int signo);
7
7
-extern int become_user(const char *username, int access_fd, int output_fd, int error_fd, int pid_fd);
8
+extern int become_user(const char *username, int pid_fd);
9
9
-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);
10
+extern int become_daemon(int dont_fork, const char *user);
11
12
extern void netdata_cleanup_and_exit(int i);
13
src/log.c
+132
-8
@@ -1,20 +1,125 @@
1
#include "common.h"
2
3
-// ----------------------------------------------------------------------------
4
-// LOG
5
-
3
const char *program_name = "";
4
unsigned long long debug_flags = DEBUG;
5
9
-int silent = 0;
10
-
11
-int access_fd = -1;
12
-FILE *stdaccess = NULL;
13
-
6
int access_log_syslog = 1;
7
int error_log_syslog = 1;
8
int output_log_syslog = 1; // debug log
9
10
+int stdaccess_fd = -1;
11
+FILE *stdaccess = NULL;
12
+
13
+const char *stdaccess_filename = NULL;
14
+const char *stderr_filename = NULL;
15
+const char *stdout_filename = NULL;
16
+
17
+void syslog_init(void) {
18
+ static int i = 0;
19
+
20
+ if(!i) {
21
+ openlog(program_name, LOG_PID, LOG_DAEMON);
22
+ i = 1;
23
+ }
24
+}
25
+
26
+int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) {
27
+ int f, t;
28
+
29
+ if(!filename || !*filename || !strcmp(filename, "none"))
30
+ filename = "/dev/null";
31
+
32
+ if(!strcmp(filename, "syslog")) {
33
+ filename = "/dev/null";
34
+ syslog_init();
35
+ if(enabled_syslog) *enabled_syslog = 1;
36
+ }
37
+ else if(enabled_syslog) *enabled_syslog = 0;
38
+
39
+ // don't do anything if the user is willing
40
+ // to have the standard one
41
+ if(!strcmp(filename, "system"))
42
+ return fd;
43
+
44
+ if(!strcmp(filename, "stdout"))
45
+ f = STDOUT_FILENO;
46
+
47
+ else if(!strcmp(filename, "stderr"))
48
+ f = STDERR_FILENO;
49
+
50
+ else {
51
+ f = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0664);
52
+ if(f == -1) {
53
+ error("Cannot open file '%s'. Leaving %d to its default.", filename, fd);
54
+ return fd;
55
+ }
56
+ }
57
+
58
+ // if there is a level-2 file pointer
59
+ // flush it before switching the level-1 fds
60
+ if(fp && *fp)
61
+ fflush(*fp);
62
+
63
+ if(fd != f && fd != -1) {
64
+ // it automatically closes
65
+ t = dup2(f, fd);
66
+ if (t == -1) {
67
+ error("Cannot dup2() new fd %d to old fd %d for '%s'", f, fd, filename);
68
+ close(f);
69
+ return fd;
70
+ }
71
+ // info("dup2() new fd %d to old fd %d for '%s'", f, fd, filename);
72
+ close(f);
73
+ }
74
+ else fd = f;
75
+
76
+ if(fp && *fp == NULL) {
77
+ // info("fdopen(%d) on filename '%s'", fd, filename);
78
+
79
+ FILE *n = fdopen(fd, "a");
80
+ if (!n)
81
+ error("Cannot fdopen() fd %d ('%s')", fd, filename);
82
+
83
+ else {
84
+ if (setvbuf(n, NULL, _IOLBF, 0) != 0)
85
+ error("Cannot set line buffering on fd %d ('%s')", fd, filename);
86
+
87
+ if(!*fp)
88
+ *fp = n;
89
+ else {
90
+ FILE *o = *fp;
91
+ *fp = n;
92
+ fclose(o);
93
+ }
94
+ }
95
+ }
96
+
97
+ return fd;
98
+}
99
+
100
+void reopen_all_log_files() {
101
+ if(stdout_filename)
102
+ open_log_file(STDOUT_FILENO, &stdout, stdout_filename, &output_log_syslog);
103
+
104
+ if(stderr_filename)
105
+ open_log_file(STDERR_FILENO, &stderr, stderr_filename, &error_log_syslog);
106
+
107
+ if(stdaccess_filename)
108
+ stdaccess_fd = open_log_file(stdaccess_fd, &stdaccess, stdaccess_filename, &access_log_syslog);
109
+}
110
+
111
+void open_all_log_files() {
112
+ // disable stdin
113
+ open_log_file(STDIN_FILENO, &stdin, "/dev/null", NULL);
114
+
115
+ open_log_file(STDOUT_FILENO, &stdout, stdout_filename, &output_log_syslog);
116
+ open_log_file(STDERR_FILENO, &stderr, stderr_filename, &error_log_syslog);
117
+ stdaccess_fd = open_log_file(stdaccess_fd, &stdaccess, stdaccess_filename, &access_log_syslog);
118
+}
119
+
120
+// ----------------------------------------------------------------------------
121
+// error log throttling
122
+
123
time_t error_log_throttle_period = 1200;
124
unsigned long error_log_errors_per_period = 200;
125
@@ -94,6 +199,13 @@ int error_log_limit(int reset) {
199
return 0;
200
}
201
202
+// ----------------------------------------------------------------------------
203
+// print the date
204
+
205
+// FIXME
206
+// this should print the date in a buffer the way it
207
+// is now, logs from multiple threads may be multiplexed
208
+
209
void log_date(FILE *out)
210
{
211
char outstr[24];
@@ -109,6 +221,9 @@ void log_date(FILE *out)
221
fprintf(out, "%s: ", outstr);
222
}
223
224
+// ----------------------------------------------------------------------------
225
+// debug log
226
+
227
void debug_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
228
{
229
va_list args;
@@ -129,6 +244,9 @@ void debug_int( const char *file, const char *function, const unsigned long line
244
fflush(stdout);
245
}
246
247
+// ----------------------------------------------------------------------------
248
+// info log
249
+
250
void info_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
251
{
252
va_list args;
@@ -153,6 +271,9 @@ void info_int( const char *file, const char *function, const unsigned long line,
271
}
272
}
273
274
+// ----------------------------------------------------------------------------
275
+// error log
276
+
277
void error_int( const char *prefix, const char *file, const char *function, const unsigned long line, const char *fmt, ... )
278
{
279
va_list args;
@@ -207,6 +328,9 @@ void fatal_int( const char *file, const char *function, const unsigned long line
328
netdata_cleanup_and_exit(1);
329
}
330
331
+// ----------------------------------------------------------------------------
332
+// access log
333
+
334
void log_access( const char *fmt, ... )
335
{
336
va_list args;
src/log.h
+9
-4
@@ -33,11 +33,13 @@ extern unsigned long long debug_flags;
33
34
extern const char *program_name;
35
36
-extern int silent;
37
-
38
-extern int access_fd;
36
+extern int stdaccess_fd;
37
extern FILE *stdaccess;
38
39
+extern const char *stdaccess_filename;
40
+extern const char *stderr_filename;
41
+extern const char *stdout_filename;
42
+
43
extern int access_log_syslog;
44
extern int error_log_syslog;
45
extern int output_log_syslog;
@@ -46,10 +48,13 @@ extern time_t error_log_throttle_period;
48
extern unsigned long error_log_errors_per_period;
49
extern int error_log_limit(int reset);
50
51
+extern void open_all_log_files();
52
+extern void reopen_all_log_files();
53
+
54
#define error_log_limit_reset() do { error_log_limit(1); } while(0)
55
#define error_log_limit_unlimited() do { error_log_throttle_period = 0; } while(0)
56
52
-#define debug(type, args...) do { if(unlikely(!silent && (debug_flags & type))) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args); } while(0)
57
+#define debug(type, args...) do { if(unlikely(debug_flags & type)) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args); } while(0)
58
#define info(args...) info_int(__FILE__, __FUNCTION__, __LINE__, ##args)
59
#define infoerr(args...) error_int("INFO", __FILE__, __FUNCTION__, __LINE__, ##args)
60
#define error(args...) error_int("ERROR", __FILE__, __FUNCTION__, __LINE__, ##args)
src/main.c
+21
-51
@@ -420,10 +420,6 @@ int main(int argc, char **argv)
420
// cd to /tmp to avoid any plugins writing files at random places
421
if(chdir("/tmp")) error("netdata: ERROR: Cannot cd to /tmp");
422
423
- char *input_log_file = NULL;
424
- char *output_log_file = NULL;
425
- char *error_log_file = NULL;
426
- char *access_log_file = NULL;
423
char *user = NULL;
424
{
425
char *flags = config_get("global", "debug flags", "0x00000000");
@@ -449,36 +445,14 @@ int main(int argc, char **argv)
445
446
// --------------------------------------------------------------------
447
452
-
448
global_host_prefix = config_get("global", "host access prefix", "");
449
setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1);
450
451
// --------------------------------------------------------------------
452
458
- output_log_file = config_get("global", "debug log", LOG_DIR "/debug.log");
459
- if(strcmp(output_log_file, "syslog") == 0) {
460
- output_log_syslog = 1;
461
- output_log_file = NULL;
462
- }
463
- else if(strcmp(output_log_file, "none") == 0) {
464
- output_log_syslog = 0;
465
- output_log_file = NULL;
466
- }
467
- else output_log_syslog = 0;
468
-
469
- // --------------------------------------------------------------------
470
-
471
- error_log_file = config_get("global", "error log", LOG_DIR "/error.log");
472
- if(strcmp(error_log_file, "syslog") == 0) {
473
- error_log_syslog = 1;
474
- error_log_file = NULL;
475
- }
476
- else if(strcmp(error_log_file, "none") == 0) {
477
- error_log_syslog = 0;
478
- error_log_file = NULL;
479
- // optimization - do not even generate debug log entries
480
- }
481
- else error_log_syslog = 0;
453
+ stdout_filename = config_get("global", "debug log", LOG_DIR "/debug.log");
454
+ stderr_filename = config_get("global", "error log", LOG_DIR "/error.log");
455
+ stdaccess_filename = config_get("global", "access log", LOG_DIR "/access.log");
456
457
error_log_throttle_period = config_get_number("global", "errors flood protection period", error_log_throttle_period);
458
setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get("global", "errors flood protection period" , ""), 1);
@@ -488,19 +462,6 @@ int main(int argc, char **argv)
462
463
// --------------------------------------------------------------------
464
491
- access_log_file = config_get("global", "access log", LOG_DIR "/access.log");
492
- if(strcmp(access_log_file, "syslog") == 0) {
493
- access_log_syslog = 1;
494
- access_log_file = NULL;
495
- }
496
- else if(strcmp(access_log_file, "none") == 0) {
497
- access_log_syslog = 0;
498
- access_log_file = NULL;
499
- }
500
- else access_log_syslog = 0;
501
-
502
- // --------------------------------------------------------------------
503
-
465
rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode)));
466
467
// --------------------------------------------------------------------
@@ -551,17 +512,13 @@ int main(int argc, char **argv)
512
error("Could not block signals for threads");
513
}
514
554
- // Catch signals which we want to use to quit savely
515
+ // Catch signals which we want to use
516
struct sigaction sa;
517
sigemptyset(&sa.sa_mask);
557
- sigaddset(&sa.sa_mask, SIGHUP);
518
sigaddset(&sa.sa_mask, SIGINT);
519
sigaddset(&sa.sa_mask, SIGTERM);
520
sa.sa_handler = sig_handler_exit;
521
sa.sa_flags = 0;
562
- if(sigaction(SIGHUP, &sa, NULL) == -1) {
563
- error("Failed to change signal handler for SIGHUP");
564
- }
522
if(sigaction(SIGINT, &sa, NULL) == -1) {
523
error("Failed to change signal handler for SIGINT");
524
}
@@ -569,7 +526,17 @@ int main(int argc, char **argv)
526
error("Failed to change signal handler for SIGTERM");
527
}
528
529
+ sigemptyset(&sa.sa_mask);
530
+ sigaddset(&sa.sa_mask, SIGHUP);
531
+ sa.sa_handler = sig_handler_logrotate;
532
+ sa.sa_flags = 0;
533
+ if(sigaction(SIGHUP, &sa, NULL) == -1) {
534
+ error("Failed to change signal handler for SIGHUP");
535
+ }
536
+
537
// save database on SIGUSR1
538
+ sigemptyset(&sa.sa_mask);
539
+ sigaddset(&sa.sa_mask, SIGUSR1);
540
sa.sa_handler = sig_handler_save;
541
if(sigaction(SIGUSR1, &sa, NULL) == -1) {
542
error("Failed to change signal handler for SIGUSR1");
@@ -578,6 +545,8 @@ int main(int argc, char **argv)
545
// Ignore SIGPIPE completely.
546
// INFO: If we add signals here we have to unblock them
547
// at popen.c when running a external plugin.
548
+ sigemptyset(&sa.sa_mask);
549
+ sigaddset(&sa.sa_mask, SIGPIPE);
550
sa.sa_handler = SIG_IGN;
551
if(sigaction(SIGPIPE, &sa, NULL) == -1) {
552
error("Failed to change signal handler for SIGPIPE");
@@ -621,7 +590,11 @@ int main(int argc, char **argv)
590
create_listen_sockets();
591
}
592
624
- if(become_daemon(dont_fork, 0, user, input_log_file, output_log_file, error_log_file, access_log_file, &access_fd, &stdaccess) == -1)
593
+ // initialize the log files
594
+ open_all_log_files();
595
+
596
+ // become daemon, switch user, create pid file, set process attributes
597
+ if(become_daemon(dont_fork, user) == -1)
598
fatal("Cannot demonize myself.");
599
600
#ifdef NETDATA_INTERNAL_CHECKS
@@ -633,9 +606,6 @@ int main(int argc, char **argv)
606
}
607
#endif /* NETDATA_INTERNAL_CHECKS */
608
636
- if(output_log_syslog || error_log_syslog || access_log_syslog)
637
- openlog("netdata", LOG_PID, LOG_DAEMON);
638
-
609
info("NetData started on pid %d", getpid());
610
611
system/netdata.logrotate.in
+4
-10
@@ -6,14 +6,8 @@
6
delaycompress
7
notifempty
8
sharedscripts
9
- #
10
- # if you add netdata to your init.d/system.d
11
- # comment su & copytruncate and uncomment postrotate
12
- # to have netdata restart when logs are rotated
13
- create 0640 netdata netdata
14
- copytruncate
15
- #
16
- #postrotate
17
- # /sbin/service netdata try-restart >/dev/null
18
- #endscript
9
+ create 0664 netdata netdata
10
+ postrotate
11
+ /sbin/killall -HUP netdata
12
+ endscript
13
}
system/netdata.service.in
+25
-8
@@ -1,27 +1,44 @@
1
[Unit]
2
-Description=Linux real time system monitoring, done right
2
+Description=Real time performance monitoring
3
After=network.target httpd.service squid.service nfs-server.service mysqld.service named.service postfix.service
4
5
[Service]
6
-Type=forking
6
+Type=simple
7
WorkingDirectory=/tmp
8
User=netdata
9
Group=netdata
10
RuntimeDirectory=netdata
11
-PIDFile=@localstatedir_POST@/run/netdata/netdata.pid
12
-ExecStart=@sbindir_POST@/netdata -P @localstatedir_POST@/run/netdata/netdata.pid
11
+ExecStartPre=/bin/mkdir -p @localstatedir_POST@/run/netdata
12
+ExecStartPre=/bin/chown -R netdata:netdata @localstatedir_POST@/run/netdata
13
+ExecStartPre=/bin/chmod 0775 @localstatedir_POST@/run/netdata
14
+ExecStart=@sbindir_POST@/netdata -D -P @localstatedir_POST@/run/netdata/netdata.pid
15
+
16
+# -----------------------------------------------------------------------------
17
+# Stopping netdata
18
+
19
KillMode=mixed
20
KillSignal=SIGTERM
15
-TimeoutStopSec=30
21
17
-#Hardening
22
+# saving a big db on slow disks may need some time
23
+TimeoutStopSec=60
24
+
25
+# and disable SIGKILL - if sent during save, we will loose the db
26
+SendSIGKILL=no
27
+
28
+# -----------------------------------------------------------------------------
29
+# Hardening netdata
30
+
31
AmbientCapabilities=CAP_DAC_READ_SEARCH CAP_SYS_PTRACE
32
CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_SYS_PTRACE
33
PrivateTmp=true
34
ProtectSystem=full
35
ProtectHome=read-only
23
-#NoNewPrivileges=true is implicitly set by the MemoryDenyWriteExecute=true
24
-MemoryDenyWriteExecute=true
36
+
37
+# is implicitly set by the MemoryDenyWriteExecute=true
38
+# NoNewPrivileges=true
39
+
40
+# Do not enable - it makes node.js plugins to crash
41
+# MemoryDenyWriteExecute=true
42
43
[Install]
44
WantedBy=multi-user.target