mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
core: set $JOURNAL_STREAM to the dev_t/ino_t of the journal stream of executed services
This permits services to detect whether their stdout/stderr is connected to the journal, and if so talk to the journal directly, thus permitting carrying of metadata. As requested by the gtk folks: #2473
This commit is contained in:
parent
fd1f9c89f7
commit
7bce046bcf
@ -249,6 +249,7 @@ AC_CHECK_SIZEOF(uid_t)
|
||||
AC_CHECK_SIZEOF(gid_t)
|
||||
AC_CHECK_SIZEOF(time_t)
|
||||
AC_CHECK_SIZEOF(dev_t)
|
||||
AC_CHECK_SIZEOF(ino_t)
|
||||
AC_CHECK_SIZEOF(rlim_t,,[
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
@ -1539,6 +1539,26 @@
|
||||
<citerefentry project='man-pages'><refentrytitle>termcap</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>$JOURNAL_STREAM</varname></term>
|
||||
|
||||
<listitem><para>If the standard output or standard error output of the executed processes are connected to the
|
||||
journal (for example, by setting <varname>StandardError=journal</varname>) <varname>$JOURNAL_STREAM</varname>
|
||||
contains the device and inode numbers of the connection file descriptor, formatted in decimal, separated by a
|
||||
colon (<literal>:</literal>). This permits invoked processes to safely detect whether their standard output or
|
||||
standard error output are connected to the journal. The device and inode numbers of the file descriptors should
|
||||
be compared with the values set in the environment variable to determine whether the process output is still
|
||||
connected to the journal. Note that it is generally not sufficient to only check whether
|
||||
<varname>$JOURNAL_STREAM</varname> is set at all as services might invoke external processes replacing their
|
||||
standard output or standard error output, without unsetting the environment variable.</para>
|
||||
|
||||
<para>This environment variable is primarily useful to allow services to optionally upgrade their used log
|
||||
protocol to the native journal protocol (using
|
||||
<citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry> and other
|
||||
functions) if their standard output or standard error output is connected to the journal anyway, thus enabling
|
||||
delivery of structured metadata along with logged messages.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>Additional variables may be configured by the following
|
||||
|
@ -61,3 +61,19 @@
|
||||
#else
|
||||
# error Unknown rlim_t size
|
||||
#endif
|
||||
|
||||
#if SIZEOF_DEV_T == 8
|
||||
# define DEV_FMT "%" PRIu64
|
||||
#elif SIZEOF_DEV_T == 4
|
||||
# define DEV_FMT "%" PRIu32
|
||||
#else
|
||||
# error Unknown dev_t size
|
||||
#endif
|
||||
|
||||
#if SIZEOF_INO_T == 8
|
||||
# define INO_FMT "%" PRIu64
|
||||
#elif SIZEOF_INO_T == 4
|
||||
# define INO_FMT "%" PRIu32
|
||||
#else
|
||||
# error Unknown ino_t size
|
||||
#endif
|
||||
|
@ -454,7 +454,10 @@ static int setup_output(
|
||||
int fileno,
|
||||
int socket_fd,
|
||||
const char *ident,
|
||||
uid_t uid, gid_t gid) {
|
||||
uid_t uid,
|
||||
gid_t gid,
|
||||
dev_t *journal_stream_dev,
|
||||
ino_t *journal_stream_ino) {
|
||||
|
||||
ExecOutput o;
|
||||
ExecInput i;
|
||||
@ -464,6 +467,8 @@ static int setup_output(
|
||||
assert(context);
|
||||
assert(params);
|
||||
assert(ident);
|
||||
assert(journal_stream_dev);
|
||||
assert(journal_stream_ino);
|
||||
|
||||
if (fileno == STDOUT_FILENO && params->stdout_fd >= 0) {
|
||||
|
||||
@ -543,6 +548,17 @@ static int setup_output(
|
||||
if (r < 0) {
|
||||
log_unit_error_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m", fileno == STDOUT_FILENO ? "stdout" : "stderr");
|
||||
r = open_null_as(O_WRONLY, fileno);
|
||||
} else {
|
||||
struct stat st;
|
||||
|
||||
/* If we connected this fd to the journal via a stream, patch the device/inode into the passed
|
||||
* parameters, but only then. This is useful so that we can set $JOURNAL_STREAM that permits
|
||||
* services to detect whether they are connected to the journal or not. */
|
||||
|
||||
if (fstat(fileno, &st) >= 0) {
|
||||
*journal_stream_dev = st.st_dev;
|
||||
*journal_stream_ino = st.st_ino;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
|
||||
@ -1286,6 +1302,8 @@ static int build_environment(
|
||||
const char *home,
|
||||
const char *username,
|
||||
const char *shell,
|
||||
dev_t journal_stream_dev,
|
||||
ino_t journal_stream_ino,
|
||||
char ***ret) {
|
||||
|
||||
_cleanup_strv_free_ char **our_env = NULL;
|
||||
@ -1295,7 +1313,7 @@ static int build_environment(
|
||||
assert(c);
|
||||
assert(ret);
|
||||
|
||||
our_env = new0(char*, 11);
|
||||
our_env = new0(char*, 12);
|
||||
if (!our_env)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1367,8 +1385,15 @@ static int build_environment(
|
||||
our_env[n_env++] = x;
|
||||
}
|
||||
|
||||
if (journal_stream_dev != 0 && journal_stream_ino != 0) {
|
||||
if (asprintf(&x, "JOURNAL_STREAM=" DEV_FMT ":" INO_FMT, journal_stream_dev, journal_stream_ino) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
our_env[n_env++] = x;
|
||||
}
|
||||
|
||||
our_env[n_env++] = NULL;
|
||||
assert(n_env <= 11);
|
||||
assert(n_env <= 12);
|
||||
|
||||
*ret = our_env;
|
||||
our_env = NULL;
|
||||
@ -1481,10 +1506,12 @@ static int exec_child(
|
||||
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **final_argv = NULL;
|
||||
_cleanup_free_ char *mac_selinux_context_net = NULL;
|
||||
const char *username = NULL, *home = NULL, *shell = NULL, *wd;
|
||||
dev_t journal_stream_dev = 0;
|
||||
ino_t journal_stream_ino = 0;
|
||||
bool needs_mount_namespace;
|
||||
uid_t uid = UID_INVALID;
|
||||
gid_t gid = GID_INVALID;
|
||||
int i, r;
|
||||
bool needs_mount_namespace;
|
||||
|
||||
assert(unit);
|
||||
assert(command);
|
||||
@ -1584,13 +1611,13 @@ static int exec_child(
|
||||
return r;
|
||||
}
|
||||
|
||||
r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid);
|
||||
r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_STDOUT;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid);
|
||||
r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_STDERR;
|
||||
return r;
|
||||
@ -1729,7 +1756,16 @@ static int exec_child(
|
||||
}
|
||||
}
|
||||
|
||||
r = build_environment(context, params, n_fds, home, username, shell, &our_env);
|
||||
r = build_environment(
|
||||
context,
|
||||
params,
|
||||
n_fds,
|
||||
home,
|
||||
username,
|
||||
shell,
|
||||
journal_stream_dev,
|
||||
journal_stream_ino,
|
||||
&our_env);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_MEMORY;
|
||||
return r;
|
||||
|
Loading…
Reference in New Issue
Block a user