Add support for pipe logging for server.errorlog (fixes #296)
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2466 152afb58-edef-0310-8abb-c4023f1b3aa9svn/tags/lighttpd-1.4.23
parent
a8ad0477a8
commit
1527160c69
1
NEWS
1
NEWS
|
@ -18,6 +18,7 @@ NEWS
|
|||
* Add proper SUID bit detection (fixes #416)
|
||||
* Check for regular file in mod_cgi, so we don't try to start directories
|
||||
* Include mmap.h from chunk.h to fix some problems with #define mmap mmap64 (fixes #1923)
|
||||
* Add support for pipe logging for server.errorlog (fixes #296)
|
||||
|
||||
- 1.4.22 - 2009-03-07
|
||||
* Fix wrong lua type for CACHE_MISS/CACHE_HIT in mod_cml (fixes #533)
|
||||
|
|
|
@ -537,7 +537,7 @@ typedef struct server {
|
|||
|
||||
/* the errorlog */
|
||||
int errorlog_fd;
|
||||
enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
|
||||
enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG, ERRORLOG_PIPE } errorlog_mode;
|
||||
buffer *errorlog_buf;
|
||||
|
||||
fdevents *ev, *ev_ins;
|
||||
|
|
102
src/log.c
102
src/log.c
|
@ -54,13 +54,94 @@ int openDevNull(int fd) {
|
|||
return (tmpfd != -1) ? 0 : -1;
|
||||
}
|
||||
|
||||
int open_logfile_or_pipe(server *srv, const char* logfile) {
|
||||
int fd;
|
||||
|
||||
if (logfile[0] == '|') {
|
||||
#ifdef HAVE_FORK
|
||||
/* create write pipe and spawn process */
|
||||
|
||||
int to_log_fds[2];
|
||||
pid_t pid;
|
||||
int i;
|
||||
|
||||
if (pipe(to_log_fds)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* fork, execve */
|
||||
switch (pid = fork()) {
|
||||
case 0:
|
||||
/* child */
|
||||
close(STDIN_FILENO);
|
||||
|
||||
/* dup the filehandle to STDIN */
|
||||
if (to_log_fds[0] != STDIN_FILENO) {
|
||||
if (STDIN_FILENO != dup2(to_log_fds[0], STDIN_FILENO)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ss",
|
||||
"dup2 failed: ", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
close(to_log_fds[0]);
|
||||
}
|
||||
close(to_log_fds[1]);
|
||||
|
||||
#ifndef FD_CLOEXEC
|
||||
/* we don't need the client socket */
|
||||
for (i = 3; i < 256; i++) {
|
||||
close(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* close old stderr */
|
||||
openDevNull(STDERR_FILENO);
|
||||
|
||||
/* exec the log-process (skip the | ) */
|
||||
execl("/bin/sh", "sh", "-c", logfile + 1, NULL);
|
||||
log_error_write(srv, __FILE__, __LINE__, "sss",
|
||||
"spawning log process failed: ", strerror(errno),
|
||||
logfile + 1);
|
||||
|
||||
exit(-1);
|
||||
break;
|
||||
case -1:
|
||||
/* error */
|
||||
log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed: ", strerror(errno));
|
||||
return -1;
|
||||
default:
|
||||
close(to_log_fds[0]);
|
||||
fd = to_log_fds[1];
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else if (-1 == (fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "SSSS",
|
||||
"opening errorlog '", logfile,
|
||||
"' failed: ", strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* open the errorlog
|
||||
*
|
||||
* we have 3 possibilities:
|
||||
* we have 4 possibilities:
|
||||
* - stderr (default)
|
||||
* - syslog
|
||||
* - logfile
|
||||
* - pipe
|
||||
*
|
||||
* if the open failed, report to the user and die
|
||||
*
|
||||
|
@ -80,18 +161,10 @@ int log_error_open(server *srv) {
|
|||
} else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
|
||||
const char *logfile = srv->srvconf.errorlog_file->ptr;
|
||||
|
||||
if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "SSSS",
|
||||
"opening errorlog '", logfile,
|
||||
"' failed: ", strerror(errno));
|
||||
|
||||
if (-1 == (srv->errorlog_fd = open_logfile_or_pipe(srv, logfile))) {
|
||||
return -1;
|
||||
}
|
||||
#ifdef FD_CLOEXEC
|
||||
/* close fd on exec (cgi) */
|
||||
fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
srv->errorlog_mode = ERRORLOG_FILE;
|
||||
srv->errorlog_mode = (logfile[0] == '|') ? ERRORLOG_PIPE : ERRORLOG_FILE;
|
||||
}
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "s", "server started");
|
||||
|
@ -122,7 +195,7 @@ int log_error_open(server *srv) {
|
|||
*/
|
||||
|
||||
int log_error_cycle(server *srv) {
|
||||
/* only cycle if we are not in syslog-mode */
|
||||
/* only cycle if the error log is a file */
|
||||
|
||||
if (srv->errorlog_mode == ERRORLOG_FILE) {
|
||||
const char *logfile = srv->srvconf.errorlog_file->ptr;
|
||||
|
@ -130,7 +203,7 @@ int log_error_cycle(server *srv) {
|
|||
|
||||
int new_fd;
|
||||
|
||||
if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
|
||||
if (-1 == (new_fd = open_logfile_or_pipe(srv, logfile))) {
|
||||
/* write to old log */
|
||||
log_error_write(srv, __FILE__, __LINE__, "SSSSS",
|
||||
"cycling errorlog '", logfile,
|
||||
|
@ -158,6 +231,7 @@ int log_error_cycle(server *srv) {
|
|||
|
||||
int log_error_close(server *srv) {
|
||||
switch(srv->errorlog_mode) {
|
||||
case ERRORLOG_PIPE:
|
||||
case ERRORLOG_FILE:
|
||||
close(srv->errorlog_fd);
|
||||
break;
|
||||
|
@ -177,6 +251,7 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const
|
|||
va_list ap;
|
||||
|
||||
switch(srv->errorlog_mode) {
|
||||
case ERRORLOG_PIPE:
|
||||
case ERRORLOG_FILE:
|
||||
case ERRORLOG_STDERR:
|
||||
/* cache the generated timestamp */
|
||||
|
@ -270,6 +345,7 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const
|
|||
va_end(ap);
|
||||
|
||||
switch(srv->errorlog_mode) {
|
||||
case ERRORLOG_PIPE:
|
||||
case ERRORLOG_FILE:
|
||||
buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n"));
|
||||
write(srv->errorlog_fd, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
|
||||
|
|
|
@ -10,6 +10,8 @@ int openDevNull(int fd);
|
|||
|
||||
#define WP() log_error_write(srv, __FILE__, __LINE__, "");
|
||||
|
||||
int open_logfile_or_pipe(server *srv, const char* logfile);
|
||||
|
||||
int log_error_open(server *srv);
|
||||
int log_error_close(server *srv);
|
||||
int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
|
||||
|
|
|
@ -475,74 +475,9 @@ SETDEFAULTS_FUNC(log_access_open) {
|
|||
|
||||
if (s->access_logfile->used < 2) continue;
|
||||
|
||||
if (s->access_logfile->ptr[0] == '|') {
|
||||
#ifdef HAVE_FORK
|
||||
/* create write pipe and spawn process */
|
||||
|
||||
int to_log_fds[2];
|
||||
pid_t pid;
|
||||
|
||||
if (pipe(to_log_fds)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
|
||||
return HANDLER_ERROR;
|
||||
}
|
||||
|
||||
/* fork, execve */
|
||||
switch (pid = fork()) {
|
||||
case 0:
|
||||
/* child */
|
||||
|
||||
close(STDIN_FILENO);
|
||||
dup2(to_log_fds[0], STDIN_FILENO);
|
||||
close(to_log_fds[0]);
|
||||
/* not needed */
|
||||
close(to_log_fds[1]);
|
||||
|
||||
openDevNull(STDERR_FILENO);
|
||||
|
||||
/* we don't need the client socket */
|
||||
for (i = 3; i < 256; i++) {
|
||||
close(i);
|
||||
}
|
||||
|
||||
/* exec the log-process (skip the | )
|
||||
*
|
||||
*/
|
||||
|
||||
execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, (char *)NULL);
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "sss",
|
||||
"spawning log-process failed: ", strerror(errno),
|
||||
s->access_logfile->ptr + 1);
|
||||
|
||||
exit(-1);
|
||||
break;
|
||||
case -1:
|
||||
/* error */
|
||||
log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed: ", strerror(errno));
|
||||
break;
|
||||
default:
|
||||
close(to_log_fds[0]);
|
||||
|
||||
s->log_access_fd = to_log_fds[1];
|
||||
|
||||
break;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else if (-1 == (s->log_access_fd =
|
||||
open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssb",
|
||||
"opening access-log failed:",
|
||||
strerror(errno), s->access_logfile);
|
||||
|
||||
if (-1 == (s->log_access_fd = open_logfile_or_pipe(srv, s->access_logfile->ptr)))
|
||||
return HANDLER_ERROR;
|
||||
}
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return HANDLER_GO_ON;
|
||||
|
|
|
@ -777,16 +777,6 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
|
|||
/* not needed */
|
||||
close(to_cgi_fds[1]);
|
||||
|
||||
/* HACK:
|
||||
* this is not nice, but it works
|
||||
*
|
||||
* we feed the stderr of the CGI to our errorlog, if possible
|
||||
*/
|
||||
if (srv->errorlog_mode == ERRORLOG_FILE) {
|
||||
close(STDERR_FILENO);
|
||||
dup2(srv->errorlog_fd, STDERR_FILENO);
|
||||
}
|
||||
|
||||
/* create environment */
|
||||
env.ptr = NULL;
|
||||
env.size = 0;
|
||||
|
|
Loading…
Reference in New Issue