SD_JOURNAL_STREAM_FD(3)

πŸ’… SD_JOURNAL_STREAM_FD(3) β€” like, the whole sd_journal_stream_fd situation

okay so bestie, this is a page from the sd_journal_stream_fd manual family, and it's genuinely one of the cutest little corners of systemd. it's giving "make me a file descriptor that just writes to the journal" energy. let's get into it πŸŽ€


✨ NAME ✨

sd_journal_stream_fd, sd_journal_stream_fd_with_namespace β€” create a log stream file descriptor to the journal. that's it, that's the whole vibe πŸ¦‹


🌸 SYNOPSIS 🌸

#include <systemd/sd-journal.h>

int sd_journal_stream_fd(const char *identifier, int priority,
                         int level_prefix);

int sd_journal_stream_fd_with_namespace(const char *name_space,
                                        const char *identifier,
                                        int priority, int level_prefix);

like, look at them. two little function signatures. so demure. 🫢


πŸ’– DESCRIPTION πŸ’–

the main character: sd_journal_stream_fd()

so sd_journal_stream_fd() may be used to create a log stream file descriptor. and the way that works is honestly iconic: log messages written to this file descriptor as simple newline-separated text strings are written to the journal. no cap. just write text, get journal entries. 🫧

this file descriptor can be used internally by applications, or β€” and this is the part I'm obsessed with β€” it can be made standard output or standard error of other processes you execute. like, you can just hand it to a child process and it's logging now. main character energy fr fr πŸ‘‘

okay but what are the arguments

  • identifier β€” a short program identifier string, passed as the first argument. it gets written to the journal as the SYSLOG_IDENTIFIER= field for each log entry (peep systemd.journal-fields(7) for more deets on that). πŸ’œ
  • priority β€” the second argument, and it shall be the default priority level for all messages. it's one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG, as defined in syslog.h β€” see syslog(3) for details. yes bestie, all eight, I listed them all, you're welcome 😌
  • level_prefix β€” the third argument, and it's a boolean. if true, kernel-style log level prefixes (such as SD_WARNING) are interpreted. see sd-daemon(3) for more info on those. ⭐

the sequel: sd_journal_stream_fd_with_namespace()

sd_journal_stream_fd_with_namespace() is similar to sd_journal_stream_fd(), but it takes an additional name_space parameter that specifies which journal namespace to operate on. 🌈

  • if name_space is specified as NULL, the call is identical to sd_journal_stream_fd() β€” same function, just dressed up πŸ’…
  • for the details about journal namespaces, go read systemd-journald.service(8)

important little notes that are lowkey key

it is recommended that applications log UTF-8 messages only with this API β€” but this is not enforced. so like, nobody's gonna stop you, but the recommendation is right there, bestie πŸ™ˆ

each invocation of these functions allocates a new log stream file descriptor, that is not shared with prior or later invocations. no reusing, no hand-me-downs. 🧚

and the fd itself:

  • it's write-only (its reading direction is shut down β€” don't even try to read from it, it said no πŸ’€)
  • O_NONBLOCK is turned off initially

πŸ”₯ RETURN VALUE πŸ”₯

the call returns a valid write-only file descriptor on success, or a negative errno-style error code. so like, check it's < 0 before you go wild. πŸ“


⭐ SIGNAL SAFETY ⭐

sd_journal_stream_fd() and sd_journal_stream_fd_with_namespace() are "async signal safe" in the meaning of signal-safety(7). yup. even in a signal handler. slay. πŸŽ€


🌸 NOTES 🌸

  • all functions listed here are thread-safe and may be called in parallel from multiple threads. go off, multithreaded besties πŸ’œ
  • functions described here are available as a shared library, which can be compiled against and linked to with the libsystemd pkg-config(1) file.

πŸ¦‹ EXAMPLES πŸ¦‹

creating a log stream suitable for fprintf(3) β€” here's the whole thing, verbatim, because I would never do you dirty like that:

/* SPDX-License-Identifier: MIT-0 */

#define _GNU_SOURCE 1
#include <errno.h>
#include <syslog.h>
#include <stdio.h>
#include <unistd.h>
#include <systemd/sd-journal.h>
#include <systemd/sd-daemon.h>

int main(int argc, char *argv[]) {
  int fd;
  FILE *log;

  fd = sd_journal_stream_fd("test", LOG_INFO, 1);
  if (fd < 0) {
    fprintf(stderr, "Failed to create stream fd: %s\n", strerror(-fd));
    return 1;
  }

  log = fdopen(fd, "w");
  if (!log) {
    fprintf(stderr, "Failed to create file object: %s\n", strerror(errno));
    close(fd);
    return 1;
  }
  fprintf(log, "Hello World!\n");
  fprintf(log, SD_WARNING "This is a warning!\n");
  fclose(log);
  return 0;
}

notice how it's got the MIT-0 SPDX line at the top and everything. we stan a properly licensed example. πŸ‘‘ and yes, that SD_WARNING prefix only works because level_prefix was passed as 1. iykyk 😌


πŸ’€ HISTORY πŸ’€

  • sd_journal_stream_fd() was added in version 187. an elder. a legend. the original. 🫢
  • sd_journal_stream_fd_with_namespace() was added in version 256. the newer sibling, still iconic. ✨

πŸ”— SEE ALSO πŸ”—

systemd(1), sd-journal(3), sd-daemon(3), sd_journal_print(3), syslog(3), fprintf(3), systemd.journal-fields(7)

like, read all of them, they're all relevant, I promise, no skips πŸ’–


okay that's the whole page! and for the cute sign-off: this lil beauty comes to you from systemd 261.3, and the page itself is SD_JOURNAL_STREAM_FD(3) β€” go forth and stream your logs, bestie πŸŒˆπŸ’…πŸ«Ά

πŸ“¦ where this page comes from