2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2012-08-24 01:46:38 +02:00
|
|
|
#include <stddef.h>
|
2015-10-24 22:58:24 +02:00
|
|
|
#include <unistd.h>
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_SELINUX
|
2012-08-22 03:32:41 +02:00
|
|
|
#include <selinux/selinux.h>
|
|
|
|
#endif
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
#include "sd-daemon.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "sd-event.h"
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2015-10-26 20:07:55 +01:00
|
|
|
#include "dirent-util.h"
|
2018-11-30 22:08:41 +01:00
|
|
|
#include "env-file.h"
|
2019-04-10 19:50:53 +02:00
|
|
|
#include "errno-util.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "escape.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "fd-util.h"
|
2015-01-06 00:30:25 +01:00
|
|
|
#include "fileio.h"
|
2015-10-27 01:02:30 +01:00
|
|
|
#include "io-util.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "journald-console.h"
|
2017-07-17 23:36:35 +02:00
|
|
|
#include "journald-context.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "journald-kmsg.h"
|
2012-11-12 17:29:07 +01:00
|
|
|
#include "journald-server.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "journald-stream.h"
|
2012-08-22 03:32:41 +02:00
|
|
|
#include "journald-syslog.h"
|
2014-03-14 00:38:15 +01:00
|
|
|
#include "journald-wall.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "mkdir.h"
|
2015-10-26 16:18:16 +01:00
|
|
|
#include "parse-util.h"
|
2017-07-17 23:36:35 +02:00
|
|
|
#include "process-util.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "selinux-util.h"
|
|
|
|
#include "socket-util.h"
|
2015-10-27 01:26:31 +01:00
|
|
|
#include "stdio-util.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
2015-10-27 00:40:25 +01:00
|
|
|
#include "syslog-util.h"
|
2018-11-30 21:05:27 +01:00
|
|
|
#include "tmpfile-util.h"
|
2017-07-14 19:03:32 +02:00
|
|
|
#include "unit-name.h"
|
2012-08-22 03:32:41 +02:00
|
|
|
|
|
|
|
#define STDOUT_STREAMS_MAX 4096
|
|
|
|
|
|
|
|
typedef enum StdoutStreamState {
|
|
|
|
STDOUT_STREAM_IDENTIFIER,
|
|
|
|
STDOUT_STREAM_UNIT_ID,
|
|
|
|
STDOUT_STREAM_PRIORITY,
|
|
|
|
STDOUT_STREAM_LEVEL_PREFIX,
|
|
|
|
STDOUT_STREAM_FORWARD_TO_SYSLOG,
|
|
|
|
STDOUT_STREAM_FORWARD_TO_KMSG,
|
|
|
|
STDOUT_STREAM_FORWARD_TO_CONSOLE,
|
|
|
|
STDOUT_STREAM_RUNNING
|
|
|
|
} StdoutStreamState;
|
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
/* The different types of log record terminators: a real \n was read, a NUL character was read, the maximum line length
|
|
|
|
* was reached, or the end of the stream was reached */
|
|
|
|
|
|
|
|
typedef enum LineBreak {
|
|
|
|
LINE_BREAK_NEWLINE,
|
|
|
|
LINE_BREAK_NUL,
|
|
|
|
LINE_BREAK_LINE_MAX,
|
|
|
|
LINE_BREAK_EOF,
|
|
|
|
} LineBreak;
|
|
|
|
|
2012-08-22 03:32:41 +02:00
|
|
|
struct StdoutStream {
|
|
|
|
Server *server;
|
|
|
|
StdoutStreamState state;
|
|
|
|
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
struct ucred ucred;
|
2015-06-07 03:36:52 +02:00
|
|
|
char *label;
|
2012-08-22 03:32:41 +02:00
|
|
|
char *identifier;
|
|
|
|
char *unit_id;
|
|
|
|
int priority;
|
|
|
|
bool level_prefix:1;
|
|
|
|
bool forward_to_syslog:1;
|
|
|
|
bool forward_to_kmsg:1;
|
|
|
|
bool forward_to_console:1;
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
bool fdstore:1;
|
2015-11-01 21:50:24 +01:00
|
|
|
bool in_notify_queue:1;
|
2015-01-06 00:30:25 +01:00
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
char *buffer;
|
2012-08-22 03:32:41 +02:00
|
|
|
size_t length;
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
size_t allocated;
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2013-12-11 20:13:44 +01:00
|
|
|
sd_event_source *event_source;
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
char *state_file;
|
|
|
|
|
2017-07-17 23:36:35 +02:00
|
|
|
ClientContext *context;
|
|
|
|
|
2012-08-22 03:32:41 +02:00
|
|
|
LIST_FIELDS(StdoutStream, stdout_stream);
|
2015-11-01 21:50:24 +01:00
|
|
|
LIST_FIELDS(StdoutStream, stdout_stream_notify_queue);
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
|
2017-12-14 19:02:29 +01:00
|
|
|
char id_field[STRLEN("_STREAM_ID=") + SD_ID128_STRING_MAX];
|
2012-08-22 03:32:41 +02:00
|
|
|
};
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
void stdout_stream_free(StdoutStream *s) {
|
|
|
|
if (!s)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (s->server) {
|
2017-07-17 23:36:35 +02:00
|
|
|
|
|
|
|
if (s->context)
|
|
|
|
client_context_release(s->server, s->context);
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
assert(s->server->n_stdout_streams > 0);
|
2016-02-23 05:32:04 +01:00
|
|
|
s->server->n_stdout_streams--;
|
2015-01-06 00:30:25 +01:00
|
|
|
LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
|
2015-11-01 21:50:24 +01:00
|
|
|
|
|
|
|
if (s->in_notify_queue)
|
|
|
|
LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
|
2015-01-06 00:30:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (s->event_source) {
|
|
|
|
sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF);
|
|
|
|
s->event_source = sd_event_source_unref(s->event_source);
|
|
|
|
}
|
|
|
|
|
|
|
|
safe_close(s->fd);
|
2015-06-07 03:36:52 +02:00
|
|
|
free(s->label);
|
2015-01-06 00:30:25 +01:00
|
|
|
free(s->identifier);
|
|
|
|
free(s->unit_id);
|
|
|
|
free(s->state_file);
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
free(s->buffer);
|
2015-01-06 00:30:25 +01:00
|
|
|
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free);
|
|
|
|
|
2018-11-20 01:20:32 +01:00
|
|
|
void stdout_stream_destroy(StdoutStream *s) {
|
2015-01-06 00:30:25 +01:00
|
|
|
if (!s)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (s->state_file)
|
2015-11-01 21:50:24 +01:00
|
|
|
(void) unlink(s->state_file);
|
2015-01-06 00:30:25 +01:00
|
|
|
|
|
|
|
stdout_stream_free(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int stdout_stream_save(StdoutStream *s) {
|
|
|
|
_cleanup_free_ char *temp_path = NULL;
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
if (s->state != STDOUT_STREAM_RUNNING)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!s->state_file) {
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
r = fstat(s->fd, &st);
|
|
|
|
if (r < 0)
|
|
|
|
return log_warning_errno(errno, "Failed to stat connected stream: %m");
|
|
|
|
|
|
|
|
/* We use device and inode numbers as identifier for the stream */
|
|
|
|
if (asprintf(&s->state_file, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0)
|
|
|
|
return log_oom();
|
|
|
|
}
|
|
|
|
|
2019-03-27 11:33:50 +01:00
|
|
|
(void) mkdir_p("/run/systemd/journal/streams", 0755);
|
2015-01-06 00:30:25 +01:00
|
|
|
|
|
|
|
r = fopen_temporary(s->state_file, &f, &temp_path);
|
|
|
|
if (r < 0)
|
2015-07-29 20:31:07 +02:00
|
|
|
goto fail;
|
2015-01-06 00:30:25 +01:00
|
|
|
|
|
|
|
fprintf(f,
|
|
|
|
"# This is private data. Do not parse\n"
|
|
|
|
"PRIORITY=%i\n"
|
|
|
|
"LEVEL_PREFIX=%i\n"
|
|
|
|
"FORWARD_TO_SYSLOG=%i\n"
|
|
|
|
"FORWARD_TO_KMSG=%i\n"
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
"FORWARD_TO_CONSOLE=%i\n"
|
|
|
|
"STREAM_ID=%s\n",
|
2015-01-06 00:30:25 +01:00
|
|
|
s->priority,
|
|
|
|
s->level_prefix,
|
|
|
|
s->forward_to_syslog,
|
|
|
|
s->forward_to_kmsg,
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
s->forward_to_console,
|
2017-12-14 19:02:29 +01:00
|
|
|
s->id_field + STRLEN("_STREAM_ID="));
|
2015-01-06 00:30:25 +01:00
|
|
|
|
|
|
|
if (!isempty(s->identifier)) {
|
|
|
|
_cleanup_free_ char *escaped;
|
|
|
|
|
|
|
|
escaped = cescape(s->identifier);
|
|
|
|
if (!escaped) {
|
|
|
|
r = -ENOMEM;
|
2015-07-29 20:31:07 +02:00
|
|
|
goto fail;
|
2015-01-06 00:30:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(f, "IDENTIFIER=%s\n", escaped);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isempty(s->unit_id)) {
|
|
|
|
_cleanup_free_ char *escaped;
|
|
|
|
|
|
|
|
escaped = cescape(s->unit_id);
|
|
|
|
if (!escaped) {
|
|
|
|
r = -ENOMEM;
|
2015-07-29 20:31:07 +02:00
|
|
|
goto fail;
|
2015-01-06 00:30:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(f, "UNIT=%s\n", escaped);
|
|
|
|
}
|
|
|
|
|
|
|
|
r = fflush_and_check(f);
|
|
|
|
if (r < 0)
|
2015-07-29 20:31:07 +02:00
|
|
|
goto fail;
|
2015-01-06 00:30:25 +01:00
|
|
|
|
|
|
|
if (rename(temp_path, s->state_file) < 0) {
|
|
|
|
r = -errno;
|
2015-07-29 20:31:07 +02:00
|
|
|
goto fail;
|
2015-01-06 00:30:25 +01:00
|
|
|
}
|
|
|
|
|
2015-11-01 21:50:24 +01:00
|
|
|
if (!s->fdstore && !s->in_notify_queue) {
|
|
|
|
LIST_PREPEND(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
|
|
|
|
s->in_notify_queue = true;
|
|
|
|
|
|
|
|
if (s->server->notify_event_source) {
|
|
|
|
r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON);
|
|
|
|
if (r < 0)
|
|
|
|
log_warning_errno(r, "Failed to enable notify event source: %m");
|
|
|
|
}
|
2015-01-06 00:30:25 +01:00
|
|
|
}
|
|
|
|
|
2015-07-29 20:31:07 +02:00
|
|
|
return 0;
|
2015-01-06 00:30:25 +01:00
|
|
|
|
2015-07-29 20:31:07 +02:00
|
|
|
fail:
|
|
|
|
(void) unlink(s->state_file);
|
|
|
|
|
|
|
|
if (temp_path)
|
|
|
|
(void) unlink(temp_path);
|
2015-01-06 00:30:25 +01:00
|
|
|
|
2015-07-29 20:31:07 +02:00
|
|
|
return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file);
|
2015-01-06 00:30:25 +01:00
|
|
|
}
|
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_break) {
|
core: implement /run/systemd/units/-based path for passing unit info from PID 1 to journald
And let's make use of it to implement two new unit settings with it:
1. LogLevelMax= is a new per-unit setting that may be used to configure
log priority filtering: set it to LogLevelMax=notice and only
messages of level "notice" and lower (i.e. more important) will be
processed, all others are dropped.
2. LogExtraFields= is a new per-unit setting for configuring per-unit
journal fields, that are implicitly included in every log record
generated by the unit's processes. It takes field/value pairs in the
form of FOO=BAR.
Also, related to this, one exisiting unit setting is ported to this new
facility:
3. The invocation ID is now pulled from /run/systemd/units/ instead of
cgroupfs xattrs. This substantially relaxes requirements of systemd
on the kernel version and the privileges it runs with (specifically,
cgroupfs xattrs are not available in containers, since they are
stored in kernel memory, and hence are unsafe to permit to lesser
privileged code).
/run/systemd/units/ is a new directory, which contains a number of files
and symlinks encoding the above information. PID 1 creates and manages
these files, and journald reads them from there.
Note that this is supposed to be a direct path between PID 1 and the
journal only, due to the special runtime environment the journal runs
in. Normally, today we shouldn't introduce new interfaces that (mis-)use
a file system as IPC framework, and instead just an IPC system, but this
is very hard to do between the journal and PID 1, as long as the IPC
system is a subject PID 1 manages, and itself a client to the journal.
This patch cleans up a couple of types used in journal code:
specifically we switch to size_t for a couple of memory-sizing values,
as size_t is the right choice for everything that is memory.
Fixes: #4089
Fixes: #3041
Fixes: #4441
2017-11-02 19:43:32 +01:00
|
|
|
struct iovec *iovec;
|
2012-08-22 03:32:41 +02:00
|
|
|
int priority;
|
2013-12-10 12:17:01 +01:00
|
|
|
char syslog_priority[] = "PRIORITY=\0";
|
2017-12-14 19:02:29 +01:00
|
|
|
char syslog_facility[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int) + 1];
|
2013-12-10 12:17:01 +01:00
|
|
|
_cleanup_free_ char *message = NULL, *syslog_identifier = NULL;
|
core: implement /run/systemd/units/-based path for passing unit info from PID 1 to journald
And let's make use of it to implement two new unit settings with it:
1. LogLevelMax= is a new per-unit setting that may be used to configure
log priority filtering: set it to LogLevelMax=notice and only
messages of level "notice" and lower (i.e. more important) will be
processed, all others are dropped.
2. LogExtraFields= is a new per-unit setting for configuring per-unit
journal fields, that are implicitly included in every log record
generated by the unit's processes. It takes field/value pairs in the
form of FOO=BAR.
Also, related to this, one exisiting unit setting is ported to this new
facility:
3. The invocation ID is now pulled from /run/systemd/units/ instead of
cgroupfs xattrs. This substantially relaxes requirements of systemd
on the kernel version and the privileges it runs with (specifically,
cgroupfs xattrs are not available in containers, since they are
stored in kernel memory, and hence are unsafe to permit to lesser
privileged code).
/run/systemd/units/ is a new directory, which contains a number of files
and symlinks encoding the above information. PID 1 creates and manages
these files, and journald reads them from there.
Note that this is supposed to be a direct path between PID 1 and the
journal only, due to the special runtime environment the journal runs
in. Normally, today we shouldn't introduce new interfaces that (mis-)use
a file system as IPC framework, and instead just an IPC system, but this
is very hard to do between the journal and PID 1, as long as the IPC
system is a subject PID 1 manages, and itself a client to the journal.
This patch cleans up a couple of types used in journal code:
specifically we switch to size_t for a couple of memory-sizing values,
as size_t is the right choice for everything that is memory.
Fixes: #4089
Fixes: #3041
Fixes: #4441
2017-11-02 19:43:32 +01:00
|
|
|
size_t n = 0, m;
|
2017-07-17 23:36:35 +02:00
|
|
|
int r;
|
2012-08-22 03:32:41 +02:00
|
|
|
|
|
|
|
assert(s);
|
|
|
|
assert(p);
|
|
|
|
|
core: implement /run/systemd/units/-based path for passing unit info from PID 1 to journald
And let's make use of it to implement two new unit settings with it:
1. LogLevelMax= is a new per-unit setting that may be used to configure
log priority filtering: set it to LogLevelMax=notice and only
messages of level "notice" and lower (i.e. more important) will be
processed, all others are dropped.
2. LogExtraFields= is a new per-unit setting for configuring per-unit
journal fields, that are implicitly included in every log record
generated by the unit's processes. It takes field/value pairs in the
form of FOO=BAR.
Also, related to this, one exisiting unit setting is ported to this new
facility:
3. The invocation ID is now pulled from /run/systemd/units/ instead of
cgroupfs xattrs. This substantially relaxes requirements of systemd
on the kernel version and the privileges it runs with (specifically,
cgroupfs xattrs are not available in containers, since they are
stored in kernel memory, and hence are unsafe to permit to lesser
privileged code).
/run/systemd/units/ is a new directory, which contains a number of files
and symlinks encoding the above information. PID 1 creates and manages
these files, and journald reads them from there.
Note that this is supposed to be a direct path between PID 1 and the
journal only, due to the special runtime environment the journal runs
in. Normally, today we shouldn't introduce new interfaces that (mis-)use
a file system as IPC framework, and instead just an IPC system, but this
is very hard to do between the journal and PID 1, as long as the IPC
system is a subject PID 1 manages, and itself a client to the journal.
This patch cleans up a couple of types used in journal code:
specifically we switch to size_t for a couple of memory-sizing values,
as size_t is the right choice for everything that is memory.
Fixes: #4089
Fixes: #3041
Fixes: #4441
2017-11-02 19:43:32 +01:00
|
|
|
if (s->context)
|
|
|
|
(void) client_context_maybe_refresh(s->server, s->context, NULL, NULL, 0, NULL, USEC_INFINITY);
|
|
|
|
else if (pid_is_valid(s->ucred.pid)) {
|
|
|
|
r = client_context_acquire(s->server, s->ucred.pid, &s->ucred, s->label, strlen_ptr(s->label), s->unit_id, &s->context);
|
|
|
|
if (r < 0)
|
|
|
|
log_warning_errno(r, "Failed to acquire client context, ignoring: %m");
|
|
|
|
}
|
|
|
|
|
2012-08-22 03:32:41 +02:00
|
|
|
priority = s->priority;
|
|
|
|
|
|
|
|
if (s->level_prefix)
|
2013-12-10 12:17:01 +01:00
|
|
|
syslog_parse_priority(&p, &priority, false);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
core: implement /run/systemd/units/-based path for passing unit info from PID 1 to journald
And let's make use of it to implement two new unit settings with it:
1. LogLevelMax= is a new per-unit setting that may be used to configure
log priority filtering: set it to LogLevelMax=notice and only
messages of level "notice" and lower (i.e. more important) will be
processed, all others are dropped.
2. LogExtraFields= is a new per-unit setting for configuring per-unit
journal fields, that are implicitly included in every log record
generated by the unit's processes. It takes field/value pairs in the
form of FOO=BAR.
Also, related to this, one exisiting unit setting is ported to this new
facility:
3. The invocation ID is now pulled from /run/systemd/units/ instead of
cgroupfs xattrs. This substantially relaxes requirements of systemd
on the kernel version and the privileges it runs with (specifically,
cgroupfs xattrs are not available in containers, since they are
stored in kernel memory, and hence are unsafe to permit to lesser
privileged code).
/run/systemd/units/ is a new directory, which contains a number of files
and symlinks encoding the above information. PID 1 creates and manages
these files, and journald reads them from there.
Note that this is supposed to be a direct path between PID 1 and the
journal only, due to the special runtime environment the journal runs
in. Normally, today we shouldn't introduce new interfaces that (mis-)use
a file system as IPC framework, and instead just an IPC system, but this
is very hard to do between the journal and PID 1, as long as the IPC
system is a subject PID 1 manages, and itself a client to the journal.
This patch cleans up a couple of types used in journal code:
specifically we switch to size_t for a couple of memory-sizing values,
as size_t is the right choice for everything that is memory.
Fixes: #4089
Fixes: #3041
Fixes: #4441
2017-11-02 19:43:32 +01:00
|
|
|
if (!client_context_test_priority(s->context, priority))
|
|
|
|
return 0;
|
|
|
|
|
2015-11-17 12:23:33 +01:00
|
|
|
if (isempty(p))
|
|
|
|
return 0;
|
|
|
|
|
2012-08-22 03:32:41 +02:00
|
|
|
if (s->forward_to_syslog || s->server->forward_to_syslog)
|
|
|
|
server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
|
|
|
|
|
|
|
|
if (s->forward_to_kmsg || s->server->forward_to_kmsg)
|
|
|
|
server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred);
|
|
|
|
|
|
|
|
if (s->forward_to_console || s->server->forward_to_console)
|
|
|
|
server_forward_console(s->server, priority, s->identifier, p, &s->ucred);
|
|
|
|
|
2014-03-14 00:38:15 +01:00
|
|
|
if (s->server->forward_to_wall)
|
|
|
|
server_forward_wall(s->server, priority, s->identifier, p, &s->ucred);
|
|
|
|
|
core: implement /run/systemd/units/-based path for passing unit info from PID 1 to journald
And let's make use of it to implement two new unit settings with it:
1. LogLevelMax= is a new per-unit setting that may be used to configure
log priority filtering: set it to LogLevelMax=notice and only
messages of level "notice" and lower (i.e. more important) will be
processed, all others are dropped.
2. LogExtraFields= is a new per-unit setting for configuring per-unit
journal fields, that are implicitly included in every log record
generated by the unit's processes. It takes field/value pairs in the
form of FOO=BAR.
Also, related to this, one exisiting unit setting is ported to this new
facility:
3. The invocation ID is now pulled from /run/systemd/units/ instead of
cgroupfs xattrs. This substantially relaxes requirements of systemd
on the kernel version and the privileges it runs with (specifically,
cgroupfs xattrs are not available in containers, since they are
stored in kernel memory, and hence are unsafe to permit to lesser
privileged code).
/run/systemd/units/ is a new directory, which contains a number of files
and symlinks encoding the above information. PID 1 creates and manages
these files, and journald reads them from there.
Note that this is supposed to be a direct path between PID 1 and the
journal only, due to the special runtime environment the journal runs
in. Normally, today we shouldn't introduce new interfaces that (mis-)use
a file system as IPC framework, and instead just an IPC system, but this
is very hard to do between the journal and PID 1, as long as the IPC
system is a subject PID 1 manages, and itself a client to the journal.
This patch cleans up a couple of types used in journal code:
specifically we switch to size_t for a couple of memory-sizing values,
as size_t is the right choice for everything that is memory.
Fixes: #4089
Fixes: #3041
Fixes: #4441
2017-11-02 19:43:32 +01:00
|
|
|
m = N_IOVEC_META_FIELDS + 7 + client_context_extra_fields_n_iovec(s->context);
|
|
|
|
iovec = newa(struct iovec, m);
|
|
|
|
|
2017-09-21 13:52:34 +02:00
|
|
|
iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=stdout");
|
|
|
|
iovec[n++] = IOVEC_MAKE_STRING(s->id_field);
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
|
2017-12-14 19:02:29 +01:00
|
|
|
syslog_priority[STRLEN("PRIORITY=")] = '0' + LOG_PRI(priority);
|
2017-09-21 13:52:34 +02:00
|
|
|
iovec[n++] = IOVEC_MAKE_STRING(syslog_priority);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2013-12-10 12:17:01 +01:00
|
|
|
if (priority & LOG_FACMASK) {
|
2015-01-27 14:00:11 +01:00
|
|
|
xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
|
2017-09-21 13:52:34 +02:00
|
|
|
iovec[n++] = IOVEC_MAKE_STRING(syslog_facility);
|
2013-12-10 12:17:01 +01:00
|
|
|
}
|
2012-08-22 03:32:41 +02:00
|
|
|
|
|
|
|
if (s->identifier) {
|
|
|
|
syslog_identifier = strappend("SYSLOG_IDENTIFIER=", s->identifier);
|
|
|
|
if (syslog_identifier)
|
2017-09-21 13:52:34 +02:00
|
|
|
iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier);
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
if (line_break != LINE_BREAK_NEWLINE) {
|
|
|
|
const char *c;
|
|
|
|
|
|
|
|
/* If this log message was generated due to an uncommon line break then mention this in the log
|
|
|
|
* entry */
|
|
|
|
|
|
|
|
c = line_break == LINE_BREAK_NUL ? "_LINE_BREAK=nul" :
|
|
|
|
line_break == LINE_BREAK_LINE_MAX ? "_LINE_BREAK=line-max" :
|
|
|
|
"_LINE_BREAK=eof";
|
2017-09-21 13:52:34 +02:00
|
|
|
iovec[n++] = IOVEC_MAKE_STRING(c);
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
}
|
|
|
|
|
2012-08-22 03:32:41 +02:00
|
|
|
message = strappend("MESSAGE=", p);
|
|
|
|
if (message)
|
2017-09-21 13:52:34 +02:00
|
|
|
iovec[n++] = IOVEC_MAKE_STRING(message);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
core: implement /run/systemd/units/-based path for passing unit info from PID 1 to journald
And let's make use of it to implement two new unit settings with it:
1. LogLevelMax= is a new per-unit setting that may be used to configure
log priority filtering: set it to LogLevelMax=notice and only
messages of level "notice" and lower (i.e. more important) will be
processed, all others are dropped.
2. LogExtraFields= is a new per-unit setting for configuring per-unit
journal fields, that are implicitly included in every log record
generated by the unit's processes. It takes field/value pairs in the
form of FOO=BAR.
Also, related to this, one exisiting unit setting is ported to this new
facility:
3. The invocation ID is now pulled from /run/systemd/units/ instead of
cgroupfs xattrs. This substantially relaxes requirements of systemd
on the kernel version and the privileges it runs with (specifically,
cgroupfs xattrs are not available in containers, since they are
stored in kernel memory, and hence are unsafe to permit to lesser
privileged code).
/run/systemd/units/ is a new directory, which contains a number of files
and symlinks encoding the above information. PID 1 creates and manages
these files, and journald reads them from there.
Note that this is supposed to be a direct path between PID 1 and the
journal only, due to the special runtime environment the journal runs
in. Normally, today we shouldn't introduce new interfaces that (mis-)use
a file system as IPC framework, and instead just an IPC system, but this
is very hard to do between the journal and PID 1, as long as the IPC
system is a subject PID 1 manages, and itself a client to the journal.
This patch cleans up a couple of types used in journal code:
specifically we switch to size_t for a couple of memory-sizing values,
as size_t is the right choice for everything that is memory.
Fixes: #4089
Fixes: #3041
Fixes: #4441
2017-11-02 19:43:32 +01:00
|
|
|
server_dispatch_message(s->server, iovec, n, m, s->context, NULL, priority, 0);
|
2012-08-22 03:32:41 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) {
|
2012-08-22 03:32:41 +02:00
|
|
|
int r;
|
2015-11-17 22:42:36 +01:00
|
|
|
char *orig;
|
2012-08-22 03:32:41 +02:00
|
|
|
|
|
|
|
assert(s);
|
|
|
|
assert(p);
|
|
|
|
|
2015-11-17 22:42:36 +01:00
|
|
|
orig = p;
|
2012-08-22 03:32:41 +02:00
|
|
|
p = strstrip(p);
|
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
/* line breaks by NUL, line max length or EOF are not permissible during the negotiation part of the protocol */
|
|
|
|
if (line_break != LINE_BREAK_NEWLINE && s->state != STDOUT_STREAM_RUNNING) {
|
|
|
|
log_warning("Control protocol line not properly terminated.");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2012-08-22 03:32:41 +02:00
|
|
|
switch (s->state) {
|
|
|
|
|
|
|
|
case STDOUT_STREAM_IDENTIFIER:
|
2017-07-14 19:03:32 +02:00
|
|
|
if (!isempty(p)) {
|
2012-08-22 03:32:41 +02:00
|
|
|
s->identifier = strdup(p);
|
|
|
|
if (!s->identifier)
|
|
|
|
return log_oom();
|
|
|
|
}
|
|
|
|
|
|
|
|
s->state = STDOUT_STREAM_UNIT_ID;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case STDOUT_STREAM_UNIT_ID:
|
2017-07-14 19:03:32 +02:00
|
|
|
if (s->ucred.uid == 0 &&
|
|
|
|
unit_name_is_valid(p, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
|
|
|
|
|
|
|
|
s->unit_id = strdup(p);
|
|
|
|
if (!s->unit_id)
|
|
|
|
return log_oom();
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
s->state = STDOUT_STREAM_PRIORITY;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case STDOUT_STREAM_PRIORITY:
|
|
|
|
r = safe_atoi(p, &s->priority);
|
2013-03-11 15:10:29 +01:00
|
|
|
if (r < 0 || s->priority < 0 || s->priority > 999) {
|
2012-08-22 03:32:41 +02:00
|
|
|
log_warning("Failed to parse log priority line.");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
s->state = STDOUT_STREAM_LEVEL_PREFIX;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case STDOUT_STREAM_LEVEL_PREFIX:
|
|
|
|
r = parse_boolean(p);
|
|
|
|
if (r < 0) {
|
|
|
|
log_warning("Failed to parse level prefix line.");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-06-11 16:02:03 +02:00
|
|
|
s->level_prefix = r;
|
2012-08-22 03:32:41 +02:00
|
|
|
s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case STDOUT_STREAM_FORWARD_TO_SYSLOG:
|
|
|
|
r = parse_boolean(p);
|
|
|
|
if (r < 0) {
|
|
|
|
log_warning("Failed to parse forward to syslog line.");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-06-11 16:02:03 +02:00
|
|
|
s->forward_to_syslog = r;
|
2012-08-22 03:32:41 +02:00
|
|
|
s->state = STDOUT_STREAM_FORWARD_TO_KMSG;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case STDOUT_STREAM_FORWARD_TO_KMSG:
|
|
|
|
r = parse_boolean(p);
|
|
|
|
if (r < 0) {
|
|
|
|
log_warning("Failed to parse copy to kmsg line.");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-06-11 16:02:03 +02:00
|
|
|
s->forward_to_kmsg = r;
|
2012-08-22 03:32:41 +02:00
|
|
|
s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case STDOUT_STREAM_FORWARD_TO_CONSOLE:
|
|
|
|
r = parse_boolean(p);
|
|
|
|
if (r < 0) {
|
|
|
|
log_warning("Failed to parse copy to console line.");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-06-11 16:02:03 +02:00
|
|
|
s->forward_to_console = r;
|
2012-08-22 03:32:41 +02:00
|
|
|
s->state = STDOUT_STREAM_RUNNING;
|
2015-01-06 00:30:25 +01:00
|
|
|
|
|
|
|
/* Try to save the stream, so that journald can be restarted and we can recover */
|
|
|
|
(void) stdout_stream_save(s);
|
2012-08-22 03:32:41 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
case STDOUT_STREAM_RUNNING:
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
return stdout_stream_log(s, orig, line_break);
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
assert_not_reached("Unknown stream state");
|
|
|
|
}
|
|
|
|
|
|
|
|
static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
|
|
|
|
char *p;
|
|
|
|
size_t remaining;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
p = s->buffer;
|
|
|
|
remaining = s->length;
|
2016-09-28 07:35:48 +02:00
|
|
|
|
|
|
|
/* XXX: This function does nothing if (s->length == 0) */
|
|
|
|
|
2012-08-22 03:32:41 +02:00
|
|
|
for (;;) {
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
LineBreak line_break;
|
2012-08-22 03:32:41 +02:00
|
|
|
size_t skip;
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
char *end1, *end2;
|
|
|
|
|
|
|
|
end1 = memchr(p, '\n', remaining);
|
|
|
|
end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : remaining);
|
|
|
|
|
|
|
|
if (end2) {
|
|
|
|
/* We found a NUL terminator */
|
|
|
|
skip = end2 - p + 1;
|
|
|
|
line_break = LINE_BREAK_NUL;
|
|
|
|
} else if (end1) {
|
|
|
|
/* We found a \n terminator */
|
|
|
|
*end1 = 0;
|
|
|
|
skip = end1 - p + 1;
|
|
|
|
line_break = LINE_BREAK_NEWLINE;
|
|
|
|
} else if (remaining >= s->server->line_max) {
|
|
|
|
/* Force a line break after the maximum line length */
|
|
|
|
*(p + s->server->line_max) = 0;
|
2012-08-22 03:32:41 +02:00
|
|
|
skip = remaining;
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
line_break = LINE_BREAK_LINE_MAX;
|
2012-08-22 03:32:41 +02:00
|
|
|
} else
|
|
|
|
break;
|
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
r = stdout_stream_line(s, p, line_break);
|
2012-08-22 03:32:41 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
remaining -= skip;
|
|
|
|
p += skip;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (force_flush && remaining > 0) {
|
|
|
|
p[remaining] = 0;
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
r = stdout_stream_line(s, p, LINE_BREAK_EOF);
|
2012-08-22 03:32:41 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
p += remaining;
|
|
|
|
remaining = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p > s->buffer) {
|
|
|
|
memmove(s->buffer, p, remaining);
|
|
|
|
s->length = remaining;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-12-11 20:13:44 +01:00
|
|
|
static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
|
|
|
|
StdoutStream *s = userdata;
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
size_t limit;
|
2012-08-22 03:32:41 +02:00
|
|
|
ssize_t l;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
2013-12-11 20:13:44 +01:00
|
|
|
if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
|
|
|
|
log_error("Got invalid event from epoll for stdout stream: %"PRIx32, revents);
|
2013-12-11 22:17:15 +01:00
|
|
|
goto terminate;
|
2013-12-11 20:13:44 +01:00
|
|
|
}
|
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
/* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */
|
|
|
|
if (s->length + 1 >= s->allocated) {
|
|
|
|
if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)) {
|
|
|
|
log_oom();
|
|
|
|
goto terminate;
|
|
|
|
}
|
|
|
|
}
|
2012-08-22 03:32:41 +02:00
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
/* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also,
|
|
|
|
* always leave room for a terminating NUL we might need to add. */
|
|
|
|
limit = MIN(s->allocated - 1, s->server->line_max);
|
|
|
|
|
|
|
|
l = read(s->fd, s->buffer + s->length, limit - s->length);
|
|
|
|
if (l < 0) {
|
2012-08-22 03:32:41 +02:00
|
|
|
if (errno == EAGAIN)
|
|
|
|
return 0;
|
|
|
|
|
2014-11-28 19:29:59 +01:00
|
|
|
log_warning_errno(errno, "Failed to read from stream: %m");
|
2013-12-11 22:17:15 +01:00
|
|
|
goto terminate;
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (l == 0) {
|
2013-12-13 03:30:42 +01:00
|
|
|
stdout_stream_scan(s, true);
|
2013-12-11 22:17:15 +01:00
|
|
|
goto terminate;
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
s->length += l;
|
|
|
|
r = stdout_stream_scan(s, false);
|
|
|
|
if (r < 0)
|
2013-12-11 22:17:15 +01:00
|
|
|
goto terminate;
|
2012-08-22 03:32:41 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2013-12-11 22:17:15 +01:00
|
|
|
terminate:
|
2015-01-06 00:30:25 +01:00
|
|
|
stdout_stream_destroy(s);
|
2013-12-11 20:13:44 +01:00
|
|
|
return 0;
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
2018-11-20 01:20:32 +01:00
|
|
|
int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
|
2015-01-06 00:30:25 +01:00
|
|
|
_cleanup_(stdout_stream_freep) StdoutStream *stream = NULL;
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
sd_id128_t id;
|
2015-01-06 00:30:25 +01:00
|
|
|
int r;
|
|
|
|
|
2012-08-22 03:32:41 +02:00
|
|
|
assert(s);
|
2015-01-06 00:30:25 +01:00
|
|
|
assert(fd >= 0);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
r = sd_id128_randomize(&id);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to generate stream ID: %m");
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
stream = new0(StdoutStream, 1);
|
|
|
|
if (!stream)
|
|
|
|
return log_oom();
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
stream->fd = -1;
|
|
|
|
stream->priority = LOG_INFO;
|
2012-08-22 03:32:41 +02:00
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id));
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
r = getpeercred(fd, &stream->ucred);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to determine peer credentials: %m");
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2017-05-02 18:42:19 +02:00
|
|
|
if (mac_selinux_use()) {
|
2015-06-07 03:36:52 +02:00
|
|
|
r = getpeersec(fd, &stream->label);
|
|
|
|
if (r < 0 && r != -EOPNOTSUPP)
|
|
|
|
(void) log_warning_errno(r, "Failed to determine peer security context: %m");
|
2015-01-06 00:30:25 +01:00
|
|
|
}
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
(void) shutdown(fd, SHUT_WR);
|
|
|
|
|
|
|
|
r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLIN, stdout_stream_process, stream);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to add stream to event loop: %m");
|
|
|
|
|
|
|
|
r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to adjust stdout event source priority: %m");
|
|
|
|
|
|
|
|
stream->fd = fd;
|
|
|
|
|
|
|
|
stream->server = s;
|
|
|
|
LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
|
2016-02-23 05:32:04 +01:00
|
|
|
s->n_stdout_streams++;
|
2015-01-06 00:30:25 +01:00
|
|
|
|
|
|
|
if (ret)
|
|
|
|
*ret = stream;
|
|
|
|
|
|
|
|
stream = NULL;
|
|
|
|
|
|
|
|
return 0;
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
2013-12-11 20:13:44 +01:00
|
|
|
static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revents, void *userdata) {
|
2015-01-06 00:30:25 +01:00
|
|
|
_cleanup_close_ int fd = -1;
|
2013-12-11 20:13:44 +01:00
|
|
|
Server *s = userdata;
|
2015-01-06 00:30:25 +01:00
|
|
|
int r;
|
2012-08-22 03:32:41 +02:00
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (revents != EPOLLIN)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
|
|
|
"Got invalid event from epoll for stdout server fd: %" PRIx32,
|
|
|
|
revents);
|
2013-12-11 20:13:44 +01:00
|
|
|
|
2012-08-22 03:32:41 +02:00
|
|
|
fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
|
|
|
|
if (fd < 0) {
|
2019-04-10 19:50:53 +02:00
|
|
|
if (ERRNO_IS_ACCEPT_AGAIN(errno))
|
2012-08-22 03:32:41 +02:00
|
|
|
return 0;
|
|
|
|
|
2015-11-05 13:44:20 +01:00
|
|
|
return log_error_errno(errno, "Failed to accept stdout connection: %m");
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
|
2018-10-21 05:21:36 +02:00
|
|
|
struct ucred u;
|
|
|
|
|
|
|
|
r = getpeercred(fd, &u);
|
|
|
|
|
|
|
|
/* By closing fd here we make sure that the client won't wait too long for journald to
|
|
|
|
* gather all the data it adds to the error message to find out that the connection has
|
|
|
|
* just been refused.
|
|
|
|
*/
|
|
|
|
fd = safe_close(fd);
|
|
|
|
|
|
|
|
server_driver_message(s, r < 0 ? 0 : u.pid, NULL, LOG_MESSAGE("Too many stdout streams, refusing connection."), NULL);
|
2012-08-22 03:32:41 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
r = stdout_stream_install(s, fd, NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
fd = -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int stdout_stream_load(StdoutStream *stream, const char *fname) {
|
|
|
|
_cleanup_free_ char
|
|
|
|
*priority = NULL,
|
|
|
|
*level_prefix = NULL,
|
|
|
|
*forward_to_syslog = NULL,
|
|
|
|
*forward_to_kmsg = NULL,
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
*forward_to_console = NULL,
|
|
|
|
*stream_id = NULL;
|
2015-01-06 00:30:25 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(stream);
|
|
|
|
assert(fname);
|
|
|
|
|
|
|
|
if (!stream->state_file) {
|
|
|
|
stream->state_file = strappend("/run/systemd/journal/streams/", fname);
|
|
|
|
if (!stream->state_file)
|
|
|
|
return log_oom();
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
2018-11-12 14:04:47 +01:00
|
|
|
r = parse_env_file(NULL, stream->state_file,
|
2015-01-06 00:30:25 +01:00
|
|
|
"PRIORITY", &priority,
|
|
|
|
"LEVEL_PREFIX", &level_prefix,
|
|
|
|
"FORWARD_TO_SYSLOG", &forward_to_syslog,
|
|
|
|
"FORWARD_TO_KMSG", &forward_to_kmsg,
|
|
|
|
"FORWARD_TO_CONSOLE", &forward_to_console,
|
|
|
|
"IDENTIFIER", &stream->identifier,
|
|
|
|
"UNIT", &stream->unit_id,
|
2018-11-12 14:18:03 +01:00
|
|
|
"STREAM_ID", &stream_id);
|
2015-01-06 00:30:25 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to read: %s", stream->state_file);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
if (priority) {
|
|
|
|
int p;
|
|
|
|
|
|
|
|
p = log_level_from_string(priority);
|
|
|
|
if (p >= 0)
|
|
|
|
stream->priority = p;
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
if (level_prefix) {
|
|
|
|
r = parse_boolean(level_prefix);
|
|
|
|
if (r >= 0)
|
|
|
|
stream->level_prefix = r;
|
2013-10-10 16:35:44 +02:00
|
|
|
}
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
if (forward_to_syslog) {
|
|
|
|
r = parse_boolean(forward_to_syslog);
|
|
|
|
if (r >= 0)
|
|
|
|
stream->forward_to_syslog = r;
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
if (forward_to_kmsg) {
|
|
|
|
r = parse_boolean(forward_to_kmsg);
|
|
|
|
if (r >= 0)
|
|
|
|
stream->forward_to_kmsg = r;
|
2013-12-11 20:13:44 +01:00
|
|
|
}
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
if (forward_to_console) {
|
|
|
|
r = parse_boolean(forward_to_console);
|
|
|
|
if (r >= 0)
|
|
|
|
stream->forward_to_console = r;
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
journald: make maximum size of stream log lines configurable and bump it to 48K (#6838)
This adds a new setting LineMax= to journald.conf, and sets it by
default to 48K. When we convert stream-based stdout/stderr logging into
record-based log entries, read up to the specified amount of bytes
before forcing a line-break.
This also makes three related changes:
- When a NUL byte is read we'll not recognize this as alternative line
break, instead of silently dropping everything after it. (see #4863)
- The reason for a line-break is now encoded in the log record, if it
wasn't a plain newline. Specifically, we distuingish "nul",
"line-max" and "eof", for line breaks due to NUL byte, due to the
maximum line length as configured with LineMax= or due to end of
stream. This data is stored in the new implicit _LINE_BREAK= field.
It's not synthesized for plain \n line breaks.
- A randomized 128bit ID is assigned to each log stream.
With these three changes in place it's (mostly) possible to reconstruct
the original byte streams from log data, as (most) of the context of
the conversion from the byte stream to log records is saved now. (So,
the only bits we still drop are empty lines. Which might be something to
look into in a future change, and which is outside of the scope of this
work)
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=86465
See: #4863
Replaces: #4875
2017-09-22 10:22:24 +02:00
|
|
|
if (stream_id) {
|
|
|
|
sd_id128_t id;
|
|
|
|
|
|
|
|
r = sd_id128_from_string(stream_id, &id);
|
|
|
|
if (r >= 0)
|
|
|
|
xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id));
|
|
|
|
}
|
|
|
|
|
2015-01-06 00:30:25 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int stdout_stream_restore(Server *s, const char *fname, int fd) {
|
|
|
|
StdoutStream *stream;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
assert(fname);
|
|
|
|
assert(fd >= 0);
|
|
|
|
|
|
|
|
if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
|
|
|
|
log_warning("Too many stdout streams, refusing restoring of stream.");
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = stdout_stream_install(s, fd, &stream);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
stream->state = STDOUT_STREAM_RUNNING;
|
|
|
|
stream->fdstore = true;
|
|
|
|
|
|
|
|
/* Ignore all parsing errors */
|
|
|
|
(void) stdout_stream_load(stream, fname);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
|
|
|
return 0;
|
2015-01-06 00:30:25 +01:00
|
|
|
}
|
|
|
|
|
2015-08-02 01:53:03 +02:00
|
|
|
int server_restore_streams(Server *s, FDSet *fds) {
|
2015-01-06 00:30:25 +01:00
|
|
|
_cleanup_closedir_ DIR *d = NULL;
|
|
|
|
struct dirent *de;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
d = opendir("/run/systemd/journal/streams");
|
|
|
|
if (!d) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return log_warning_errno(errno, "Failed to enumerate /run/systemd/journal/streams: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
FOREACH_DIRENT(de, d, goto fail) {
|
|
|
|
unsigned long st_dev, st_ino;
|
|
|
|
bool found = false;
|
|
|
|
Iterator i;
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
FDSET_FOREACH(fd, fds, i) {
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (fstat(fd, &st) < 0)
|
|
|
|
return log_error_errno(errno, "Failed to stat %s: %m", de->d_name);
|
|
|
|
|
|
|
|
if (S_ISSOCK(st.st_mode) && st.st_dev == st_dev && st.st_ino == st_ino) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
/* No file descriptor? Then let's delete the state file */
|
|
|
|
log_debug("Cannot restore stream file %s", de->d_name);
|
2018-02-16 07:00:22 +01:00
|
|
|
if (unlinkat(dirfd(d), de->d_name, 0) < 0)
|
2018-06-05 20:18:47 +02:00
|
|
|
log_warning_errno(errno, "Failed to remove /run/systemd/journal/streams/%s: %m",
|
|
|
|
de->d_name);
|
2015-01-06 00:30:25 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
fdset_remove(fds, fd);
|
|
|
|
|
|
|
|
r = stdout_stream_restore(s, de->d_name, fd);
|
|
|
|
if (r < 0)
|
|
|
|
safe_close(fd);
|
|
|
|
}
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2013-12-13 03:30:42 +01:00
|
|
|
return 0;
|
2015-01-06 00:30:25 +01:00
|
|
|
|
|
|
|
fail:
|
|
|
|
return log_error_errno(errno, "Failed to read streams directory: %m");
|
2012-08-22 03:32:41 +02:00
|
|
|
}
|
|
|
|
|
2015-08-02 01:53:03 +02:00
|
|
|
int server_open_stdout_socket(Server *s) {
|
2016-05-05 22:24:36 +02:00
|
|
|
static const union sockaddr_union sa = {
|
|
|
|
.un.sun_family = AF_UNIX,
|
|
|
|
.un.sun_path = "/run/systemd/journal/stdout",
|
|
|
|
};
|
2012-08-22 03:32:41 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
if (s->stdout_fd < 0) {
|
|
|
|
s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
2014-11-28 19:57:32 +01:00
|
|
|
if (s->stdout_fd < 0)
|
|
|
|
return log_error_errno(errno, "socket() failed: %m");
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2018-10-15 12:08:30 +02:00
|
|
|
(void) sockaddr_un_unlink(&sa.un);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2016-05-05 22:24:36 +02:00
|
|
|
r = bind(s->stdout_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
|
2014-11-28 19:57:32 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2015-04-13 04:43:08 +02:00
|
|
|
(void) chmod(sa.un.sun_path, 0666);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2014-11-28 19:57:32 +01:00
|
|
|
if (listen(s->stdout_fd, SOMAXCONN) < 0)
|
|
|
|
return log_error_errno(errno, "listen(%s) failed: %m", sa.un.sun_path);
|
2012-08-22 03:32:41 +02:00
|
|
|
} else
|
2018-10-12 18:26:02 +02:00
|
|
|
(void) fd_nonblock(s->stdout_fd, true);
|
2012-08-22 03:32:41 +02:00
|
|
|
|
2014-02-19 23:54:58 +01:00
|
|
|
r = sd_event_add_io(s->event, &s->stdout_event_source, s->stdout_fd, EPOLLIN, stdout_stream_new, s);
|
2014-11-28 18:23:20 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to add stdout server fd to event source: %m");
|
2013-12-11 20:13:44 +01:00
|
|
|
|
2016-01-08 21:11:44 +01:00
|
|
|
r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+5);
|
2014-11-28 18:23:20 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");
|
2012-08-22 03:32:41 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2015-11-01 21:50:24 +01:00
|
|
|
|
|
|
|
void stdout_stream_send_notify(StdoutStream *s) {
|
|
|
|
struct iovec iovec = {
|
|
|
|
.iov_base = (char*) "FDSTORE=1",
|
2017-12-14 19:02:29 +01:00
|
|
|
.iov_len = STRLEN("FDSTORE=1"),
|
2015-11-01 21:50:24 +01:00
|
|
|
};
|
|
|
|
struct msghdr msghdr = {
|
|
|
|
.msg_iov = &iovec,
|
|
|
|
.msg_iovlen = 1,
|
|
|
|
};
|
|
|
|
struct cmsghdr *cmsg;
|
|
|
|
ssize_t l;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
assert(!s->fdstore);
|
|
|
|
assert(s->in_notify_queue);
|
|
|
|
assert(s->server);
|
|
|
|
assert(s->server->notify_fd >= 0);
|
|
|
|
|
|
|
|
/* Store the connection fd in PID 1, so that we get it passed
|
|
|
|
* in again on next start */
|
|
|
|
|
|
|
|
msghdr.msg_controllen = CMSG_SPACE(sizeof(int));
|
|
|
|
msghdr.msg_control = alloca0(msghdr.msg_controllen);
|
|
|
|
|
|
|
|
cmsg = CMSG_FIRSTHDR(&msghdr);
|
|
|
|
cmsg->cmsg_level = SOL_SOCKET;
|
|
|
|
cmsg->cmsg_type = SCM_RIGHTS;
|
|
|
|
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
|
|
|
|
|
|
|
memcpy(CMSG_DATA(cmsg), &s->fd, sizeof(int));
|
|
|
|
|
|
|
|
l = sendmsg(s->server->notify_fd, &msghdr, MSG_DONTWAIT|MSG_NOSIGNAL);
|
|
|
|
if (l < 0) {
|
|
|
|
if (errno == EAGAIN)
|
|
|
|
return;
|
|
|
|
|
|
|
|
log_error_errno(errno, "Failed to send stream file descriptor to service manager: %m");
|
|
|
|
} else {
|
|
|
|
log_debug("Successfully sent stream file descriptor to service manager.");
|
|
|
|
s->fdstore = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
|
|
|
|
s->in_notify_queue = false;
|
|
|
|
|
|
|
|
}
|