I've got a system with several daemons running (as systemd units) that output log information to the journal in Arch Linux. I want to direct the journal output of some of those unit files into a separate text file whose location I specify, essentially creating a log file for a subset of units. How can I go about doing that?
The file:path option may be used to connect a specific file system object to standard output. The semantics are similar to the same option of StandardInput=, see above. If path refers to a regular file on the filesystem, it is opened (created if it doesn't exist yet) for writing at the beginning of the file, but without truncating it. If standard input and output are directed to the same file path, it is opened only once, for reading as well as writing and duplicated. This is particularly useful when the specified path refers to an AF_UNIX socket in the file system, as in that case only a single stream connection is created for both input and output.
append:path is similar to file:path above, but it opens the file in append mode.
truncate:path is similar to file:path above, but it truncates the file when opening it. For units with multiple command lines, e.g. Type=oneshot services with multiple ExecStart=, or services with ExecCondition=, ExecStartPre= or ExecStartPost=, the output file is reopened and therefore re-truncated for each command line. If the output file is truncated while another process still has the file open, e.g. by an ExecReload= running concurrently with an ExecStart=, and the other process continues writing to the file without adjusting its offset, then the space between the file pointers of the two processes may be filled with NUL bytes, producing a sparse file. Thus, truncate:path is typically only useful for units where only one process runs at a time, such as services with a single ExecStart= and no ExecStartPost=, ExecReload=, ExecStop= or similar.
The fd:name option connects standard output to a specific, named file descriptor provided by a socket unit. A name may be specified as part of this option, following a ":" character (e.g. "fd:foobar"). If no name is specified, the name "stdout" is implied (i.e. "fd" is equivalent to "fd:stdout"). At least one socket unit defining the specified name must be provided via the Sockets= option, and the file descriptor name may differ from the name of its containing socket unit. If multiple matches are found, the first one will be used. See FileDescriptorName= in systemd.socket(5) for more details about named descriptors and their ordering.
Seems this is not possible and unwanted by upstream (redirecting stdout/stderr to individual files) see e.g. http://lists.freedesktop.org/archives/systemd-devel/2012-March/004705.html - read the whole thread for more context information how this is intended to work.
What you can do, is either log to syslog, and that way write to individual files. Or the other way around, if the unit calls some program which can write a log itself, then use that to log to a file.
You may also want to take a look at View stdout/stderr of systemd service
What you already can do with your current setup, is use
journalctl -u yourunitname > yourlogfile_for_yourunitname
to direct the whole journal output for your unit "yourunitname" into a file.
On the latter part, you should also take a look at the hints from Lennart from abovementioned mailing list thread:
On recent systemd versions something like
systemd-journalctl -o cat _SYSTEMD_UNIT=postgresql.serviceshould create a very simple output that only includes the actual messages and nothing else. You can even pass "-f" and make this live."
Actually, for newer systemd versions the command is only journalctl and from what I can tell, the abovementioned long command is the same as
journalctl -u yourunitname and you can also
-f there to "follow" the output (as in tailf or tail -f).