new log file management, now 3 logs are supported: access, error, debug
Costa Tsaousis (ktsaou) committed
May 3, 2014 at 15:09 UTC
2994ab47e856e9e6b69b175cc7f9d70fb4d6c425
1 file changed
+191
-98
netdata.c
+191
-98
@@ -208,14 +208,12 @@ void mypclose(FILE *fp)
208
209
unsigned long long debug_flags = DEBUG;
210
211
-char *debug_log = NULL;
212
-int debug_fd = -1;
213
-
214
-char *access_log = NULL;
211
int access_fd = -1;
212
FILE *stdaccess = NULL;
213
218
-int log_syslog = 1;
214
+int access_log_syslog = 1;
215
+int error_log_syslog = 1;
216
+int output_log_syslog = 1; // debug log
217
218
219
void log_date(FILE *out)
@@ -242,12 +240,18 @@ void debug_int( const char *file, const char *function, const unsigned long line
240
if(file) { ; }
241
va_list args;
242
245
- log_date(stderr);
243
+ log_date(stdout);
244
va_start( args, fmt );
247
- fprintf(stderr, "DEBUG (%04lu@%-15.15s): ", line, function);
248
- vfprintf( stderr, fmt, args );
245
+ fprintf(stdout, "DEBUG (%04lu@%-15.15s): ", line, function);
246
+ vfprintf( stdout, fmt, args );
247
va_end( args );
250
- fprintf(stderr, "\n");
248
+ fprintf(stdout, "\n");
249
+
250
+ if(output_log_syslog) {
251
+ va_start( args, fmt );
252
+ vsyslog(LOG_ERR, fmt, args );
253
+ va_end( args );
254
+ }
255
}
256
257
#define error(args...) error_int(__FILE__, __FUNCTION__, __LINE__, ##args)
@@ -257,22 +261,20 @@ void error_int( const char *file, const char *function, const unsigned long line
261
if(file) { ; }
262
va_list args;
263
260
- if(!silent) {
261
- log_date(stderr);
264
+ log_date(stderr);
265
263
- va_start( args, fmt );
264
- fprintf(stderr, "ERROR (%04lu@%-15.15s): ", line, function);
265
- vfprintf( stderr, fmt, args );
266
- va_end( args );
266
+ va_start( args, fmt );
267
+ fprintf(stderr, "ERROR (%04lu@%-15.15s): ", line, function);
268
+ vfprintf( stderr, fmt, args );
269
+ va_end( args );
270
268
- if(errno) {
269
- fprintf(stderr, " (errno %d, %s)\n", errno, strerror(errno));
270
- errno = 0;
271
- }
272
- else fprintf(stderr, "\n");
271
+ if(errno) {
272
+ fprintf(stderr, " (errno %d, %s)\n", errno, strerror(errno));
273
+ errno = 0;
274
}
275
+ else fprintf(stderr, "\n");
276
275
- if(log_syslog) {
277
+ if(error_log_syslog) {
278
va_start( args, fmt );
279
vsyslog(LOG_ERR, fmt, args );
280
va_end( args );
@@ -286,19 +288,17 @@ void fatal_int( const char *file, const char *function, const unsigned long line
288
if(file) { ; }
289
va_list args;
290
289
- if(!silent) {
290
- log_date(stderr);
291
+ log_date(stderr);
292
292
- va_start( args, fmt );
293
- fprintf(stderr, "FATAL (%04lu@%-15.15s): ", line, function);
294
- vfprintf( stderr, fmt, args );
295
- va_end( args );
293
+ va_start( args, fmt );
294
+ fprintf(stderr, "FATAL (%04lu@%-15.15s): ", line, function);
295
+ vfprintf( stderr, fmt, args );
296
+ va_end( args );
297
297
- perror(" # ");
298
- fprintf(stderr, "\n");
299
- }
298
+ perror(" # ");
299
+ fprintf(stderr, "\n");
300
301
- if(log_syslog) {
301
+ if(error_log_syslog) {
302
va_start( args, fmt );
303
vsyslog(LOG_CRIT, fmt, args );
304
va_end( args );
@@ -321,7 +321,7 @@ void log_access( const char *fmt, ... )
321
fflush( stdaccess );
322
}
323
324
- if(log_syslog) {
324
+ if(access_log_syslog) {
325
va_start( args, fmt );
326
vsyslog(LOG_INFO, fmt, args );
327
va_end( args );
@@ -2092,7 +2092,7 @@ void generate_config(struct web_buffer *wb, int only_changed)
2092
}
2093
2094
for(co = config_root; co ; co = co->next) {
2095
- if(strcmp(co->name, "global") == 0 || strcmp(co->name, "debug") == 0 || strcmp(co->name, "plugins") == 0) pri = 0;
2095
+ if(strcmp(co->name, "global") == 0 || strcmp(co->name, "plugins") == 0) pri = 0;
2096
else if(strncmp(co->name, "plugin:", 7) == 0) pri = 1;
2097
else pri = 2;
2098
@@ -3198,7 +3198,7 @@ void *new_client(void *ptr)
3198
// 3. spawns a new pthread to serve the client (this is optimal for keep-alive clients)
3199
// 4. cleans up old web_clients that their pthreads have been exited
3200
3201
-void syslog_allocations(void)
3201
+void log_allocations(void)
3202
{
3203
static int mem = 0;
3204
@@ -3275,7 +3275,7 @@ void *socket_listen_main(void *ptr)
3275
debug(D_WEB_CLIENT, "%llu: Removing client.", w->id);
3276
// pthread_join(w->thread, NULL);
3277
w = web_client_free(w);
3278
- syslog_allocations();
3278
+ log_allocations();
3279
}
3280
}
3281
}
@@ -6031,10 +6031,79 @@ int fd_is_valid(int fd)
6031
return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
6032
}
6033
6034
-void become_daemon()
6034
+int become_daemon(int close_all_files, const char *input, const char *output, const char *error, const char *access, int *access_fd, FILE **access_fp)
6035
{
6036
fflush(NULL);
6037
6038
+ // open the files before forking
6039
+ int input_fd = -1, output_fd = -1, error_fd = -1, dev_null = -1;
6040
+
6041
+ if(input && *input) {
6042
+ if((input_fd = open(input, O_RDONLY, 0666)) == -1) {
6043
+ fprintf(stderr, "Cannot open input file '%s' (%s).", input, strerror(errno));
6044
+ return -1;
6045
+ }
6046
+ }
6047
+
6048
+ if(output && *output) {
6049
+ if((output_fd = open(output, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
6050
+ fprintf(stderr, "Cannot open output log file '%s' (%s).", output, strerror(errno));
6051
+ if(input_fd != -1) close(input_fd);
6052
+ return -1;
6053
+ }
6054
+ }
6055
+
6056
+ if(error && *error) {
6057
+ if((error_fd = open(error, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
6058
+ fprintf(stderr, "Cannot open error log file '%s' (%s).", error, strerror(errno));
6059
+ if(input_fd != -1) close(input_fd);
6060
+ if(output_fd != -1) close(output_fd);
6061
+ return -1;
6062
+ }
6063
+ }
6064
+
6065
+ if(access && *access && access_fd) {
6066
+ if((*access_fd = open(access, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) {
6067
+ fprintf(stderr, "Cannot open access log file '%s' (%s).", access, strerror(errno));
6068
+ if(input_fd != -1) close(input_fd);
6069
+ if(output_fd != -1) close(output_fd);
6070
+ if(error_fd != -1) close(error_fd);
6071
+ return -1;
6072
+ }
6073
+
6074
+ if(access_fp) {
6075
+ *access_fp = fdopen(*access_fd, "w");
6076
+ if(!*access_fp) {
6077
+ fprintf(stderr, "Cannot migrate file's '%s' fd %d (%s).\n", access, *access_fd, strerror(errno));
6078
+ if(input_fd != -1) close(input_fd);
6079
+ if(output_fd != -1) close(output_fd);
6080
+ if(error_fd != -1) close(error_fd);
6081
+ close(*access_fd);
6082
+ *access_fd = -1;
6083
+ return -1;
6084
+ }
6085
+ }
6086
+ }
6087
+
6088
+ if((dev_null = open("/dev/null", O_RDWR, 0666)) == -1) {
6089
+ perror("Cannot open /dev/null");
6090
+ if(input_fd != -1) close(input_fd);
6091
+ if(output_fd != -1) close(output_fd);
6092
+ if(error_fd != -1) close(error_fd);
6093
+ if(access && access_fd && *access_fd != -1) {
6094
+ close(*access_fd);
6095
+ *access_fd = -1;
6096
+ if(access_fp) {
6097
+ fclose(*access_fp);
6098
+ *access_fp = NULL;
6099
+ }
6100
+ }
6101
+ return -1;
6102
+ }
6103
+
6104
+ // all files opened
6105
+ // lets do it
6106
+
6107
int i = fork();
6108
if(i == -1) {
6109
perror("cannot fork");
@@ -6066,31 +6135,62 @@ void become_daemon()
6135
umask(0);
6136
6137
// close all files
6069
- for(i = sysconf(_SC_OPEN_MAX); i > 0; i--)
6070
- if(i != debug_fd && i != access_fd && i != listen_fd && fd_is_valid(i)) close(i);
6138
+ if(close_all_files) {
6139
+ for(i = sysconf(_SC_OPEN_MAX); i > 0; i--)
6140
+ if(
6141
+ ((access_fd && i != *access_fd) || !access_fd)
6142
+ && i != dev_null
6143
+ && i != input_fd
6144
+ && i != output_fd
6145
+ && i != error_fd
6146
+ && fd_is_valid(i)
6147
+ ) close(i);
6148
+ }
6149
+ else {
6150
+ close(STDIN_FILENO);
6151
+ close(STDOUT_FILENO);
6152
+ close(STDERR_FILENO);
6153
+ }
6154
6072
- silent = 0;
6073
- if(debug_fd == -1) {
6074
- silent = 1;
6075
- debug_fd = open("/dev/null", O_RDWR | O_APPEND | O_CREAT, 0666);
6155
+ // put the opened files
6156
+ // to our standard file descriptors
6157
+ if(input_fd != -1) {
6158
+ if(input_fd != STDIN_FILENO) {
6159
+ dup2(input_fd, STDIN_FILENO);
6160
+ close(input_fd);
6161
+ }
6162
+ input_fd = -1;
6163
+ }
6164
+ else dup2(dev_null, STDIN_FILENO);
6165
+
6166
+ if(output_fd != -1) {
6167
+ if(output_fd != STDOUT_FILENO) {
6168
+ dup2(output_fd, STDOUT_FILENO);
6169
+ close(output_fd);
6170
+ }
6171
+ output_fd = -1;
6172
}
6173
+ else dup2(dev_null, STDOUT_FILENO);
6174
6078
- if(debug_fd != -1) {
6079
- if(dup2(debug_fd, STDIN_FILENO) < 0)
6080
- silent = 1;
6175
+ if(error_fd != -1) {
6176
+ if(error_fd != STDERR_FILENO) {
6177
+ dup2(error_fd, STDERR_FILENO);
6178
+ close(error_fd);
6179
+ }
6180
+ error_fd = -1;
6181
+ }
6182
+ else dup2(dev_null, STDERR_FILENO);
6183
6082
- if(dup2(debug_fd, STDOUT_FILENO) < 0)
6083
- silent = 1;
6184
+ // close /dev/null
6185
+ if(dev_null != STDIN_FILENO && dev_null != STDOUT_FILENO && dev_null != STDERR_FILENO)
6186
+ close(dev_null);
6187
6085
- if(dup2(debug_fd, STDERR_FILENO) < 0)
6086
- silent = 1;
6087
- }
6088
- else silent = 1;
6188
+ return(0);
6189
}
6190
6191
int main(int argc, char **argv)
6192
{
6093
- int i, daemon = 0;
6193
+ int i;
6194
int config_loaded = 0;
6195
6196
@@ -6107,10 +6207,7 @@ int main(int argc, char **argv)
6207
}
6208
i++;
6209
}
6110
- else if(strcmp(argv[i], "-dl") == 0 && (i+1) < argc) { config_set("debug", "log", argv[i+1]); i++; }
6111
- else if(strcmp(argv[i], "-df") == 0 && (i+1) < argc) { config_set("debug", "flags", argv[i+1]); i++; }
6112
- else if(strcmp(argv[i], "-d") == 0) { config_set_number("global", "daemon", 1); }
6113
- else if(strcmp(argv[i], "-nd") == 0) { config_set_number("global", "daemon", 0); }
6210
+ else if(strcmp(argv[i], "-df") == 0 && (i+1) < argc) { config_set("global", "debug flags", argv[i+1]); i++; }
6211
else if(strcmp(argv[i], "-p") == 0 && (i+1) < argc) { config_set("global", "port", argv[i+1]); i++; }
6212
else if(strcmp(argv[i], "-u") == 0 && (i+1) < argc) { config_set("global", "run as user", argv[i+1]); i++; }
6213
else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set("global", "history", argv[i+1]); i++; }
@@ -6119,13 +6216,10 @@ int main(int argc, char **argv)
6216
fprintf(stderr, "Cannot understand option '%s'.\n", argv[i]);
6217
fprintf(stderr, "\nUSAGE: %s [-d] [-l LINES_TO_SAVE] [-u UPDATE_TIMER] [-p LISTEN_PORT] [-dl debug log file] [-df debug flags].\n\n", argv[0]);
6218
fprintf(stderr, " -c CONFIG FILE the configuration file to load. Default: %s.\n", CONFIG_FILENAME);
6122
- fprintf(stderr, " -d enable daemon mode (run in the background).\n");
6123
- fprintf(stderr, " -nd disable daemon mode (do not run in the background).\n");
6219
fprintf(stderr, " -l LINES_TO_SAVE can be from 5 to %d lines in JSON data. Default: %d.\n", HISTORY_MAX, HISTORY);
6220
fprintf(stderr, " -t UPDATE_TIMER can be from 1 to %d seconds. Default: %d.\n", UPDATE_EVERY_MAX, UPDATE_EVERY);
6221
fprintf(stderr, " -p LISTEN_PORT can be from 1 to %d. Default: %d.\n", 65535, LISTEN_PORT);
6222
fprintf(stderr, " -u USERNAME can be any system username to run as. Default: none.\n");
6128
- fprintf(stderr, " -dl FILENAME write debug log to FILENAME. Default: none.\n");
6223
fprintf(stderr, " -df FLAGS debug options. Default: 0x%8llx.\n", debug_flags);
6224
exit(1);
6225
}
@@ -6133,59 +6227,58 @@ int main(int argc, char **argv)
6227
6228
if(!config_loaded) load_config(NULL, 0);
6229
6230
+ char *input_log_file = NULL;
6231
+ char *output_log_file = NULL;
6232
+ char *error_log_file = NULL;
6233
+ char *access_log_file = NULL;
6234
{
6235
char buffer[1024];
6236
6237
// --------------------------------------------------------------------
6238
6239
sprintf(buffer, "0x%08llx", debug_flags);
6142
- char *flags = config_get("debug", "flags", buffer);
6240
+ char *flags = config_get("global", "debug flags", buffer);
6241
debug_flags = strtoull(flags, NULL, 0);
6242
debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags);
6243
6244
// --------------------------------------------------------------------
6245
6148
- debug_log = config_get("debug", "log", "");
6149
- if(*debug_log) {
6150
- debug_fd = open(debug_log, O_RDWR | O_APPEND | O_CREAT, 0666);
6151
- if(debug_fd < 0) {
6152
- fprintf(stderr, "Cannot open file '%s'. Reason: %s\n", debug_log, strerror(errno));
6153
- exit(1);
6154
- }
6155
- debug(D_OPTIONS, "Debug LOG set to '%s'.", debug_log);
6246
+ output_log_file = config_get("global", "debug log", "none");
6247
+ if(strcmp(output_log_file, "syslog") == 0) {
6248
+ output_log_syslog = 1;
6249
+ output_log_file = NULL;
6250
+ }
6251
+ else if(strcmp(output_log_file, "none") == 0) {
6252
+ output_log_syslog = 0;
6253
+ output_log_file = NULL;
6254
}
6255
+ else output_log_syslog = 0;
6256
6257
// --------------------------------------------------------------------
6258
6160
- access_log = config_get("global", "access log", "syslog");
6161
- if(strcmp(access_log, "syslog") == 0) {
6162
- log_syslog = 1;
6163
- access_fd = -1;
6164
- stdaccess = NULL;
6165
-
6166
- debug(D_OPTIONS, "access log on syslog.");
6259
+ error_log_file = config_get("global", "error log", "syslog");
6260
+ if(strcmp(error_log_file, "syslog") == 0) {
6261
+ error_log_syslog = 1;
6262
+ error_log_file = NULL;
6263
}
6168
- else if(strcmp(access_log, "none") == 0) {
6169
- log_syslog = 0;
6170
- access_fd = -1;
6171
- stdaccess = NULL;
6172
- debug(D_OPTIONS, "access log disabled.");
6264
+ else if(strcmp(error_log_file, "none") == 0) {
6265
+ error_log_syslog = 0;
6266
+ error_log_file = NULL;
6267
}
6174
- else {
6175
- access_fd = open(access_log, O_WRONLY | O_APPEND | O_CREAT, 0666);
6176
- if(access_fd < 0) {
6177
- fprintf(stderr, "Cannot open file '%s'. Reason: %s\n", access_log, strerror(errno));
6178
- exit(1);
6179
- }
6268
+ else error_log_syslog = 0;
6269
6181
- stdaccess = fdopen(access_fd, "w");
6182
- if(!stdaccess) {
6183
- fprintf(stderr, "Cannot migrate file's '%s' fd %d. Reason: %s\n", access_log, access_fd, strerror(errno));
6184
- exit(1);
6185
- }
6270
+ // --------------------------------------------------------------------
6271
6187
- debug(D_OPTIONS, "access log to file '%s'.", access_log);
6272
+ access_log_file = config_get("global", "access log", "syslog");
6273
+ if(strcmp(access_log_file, "syslog") == 0) {
6274
+ access_log_syslog = 1;
6275
+ access_log_file = NULL;
6276
+ }
6277
+ else if(strcmp(access_log_file, "none") == 0) {
6278
+ access_log_syslog = 0;
6279
+ access_log_file = NULL;
6280
}
6281
+ else access_log_syslog = 0;
6282
6283
// --------------------------------------------------------------------
6284
@@ -6235,10 +6328,6 @@ int main(int argc, char **argv)
6328
else debug(D_OPTIONS, "listen port set to %d.", listen_port);
6329
6330
listen_fd = create_listen_socket(listen_port);
6238
-
6239
- // --------------------------------------------------------------------
6240
-
6241
- daemon = config_get_boolean("global", "daemon", 0);
6331
}
6332
6333
// never become a problem
@@ -6250,9 +6339,13 @@ int main(int argc, char **argv)
6339
fprintf(stderr, "\n\nWARNING:\nThis system does not support [long double] variables properly.\nArithmetic overflows and rounding errors may occur.\n\n");
6340
}
6341
6253
- if(daemon) become_daemon();
6342
+ if(become_daemon(0, input_log_file, output_log_file, error_log_file, access_log_file, &access_fd, &stdaccess) == -1) {
6343
+ fprintf(stderr, "Cannot demonize myself (%s).", strerror(errno));
6344
+ exit(1);
6345
+ }
6346
+
6347
6255
- if(log_syslog) {
6348
+ if(output_log_syslog || error_log_syslog || access_log_syslog) {
6349
openlog("netdata", LOG_PID, LOG_DAEMON);
6350
syslog(LOG_NOTICE, "netdata started.");
6351
}