mtail: unable to read from unix socket
It seems like systemd-journald support was left out due to the possiblity to read from a named pipe or unix socket. While trying to configure mtail to read from the /run/systemd/journal/syslog
where systemd-journald forwards all messages to, I got the following error
...
I1108 13:21:25.043783 2636 loader.go:224] Loaded program linecount.mtail
I1108 13:21:25.043926 2636 mtail.go:99] Tail pattern "/run/systemd/journal/syslog"
I1108 13:21:25.044052 2636 tail.go:134] AddPattern: /run/systemd/journal/syslog
I1108 13:21:25.044189 2636 log_watcher.go:268] Adding a watch on resolved path "/run/systemd/journal"
I1108 13:21:25.044335 2636 log_watcher.go:248] No abspath in watched list, added new one for /run/systemd/journal
I1108 13:21:25.044479 2636 tail.go:158] glob matches: [/run/systemd/journal/syslog]
I1108 13:21:25.044620 2636 log_watcher.go:268] Adding a watch on resolved path "/run/systemd/journal/syslog"
I1108 13:21:25.044744 2636 log_watcher.go:248] No abspath in watched list, added new one for /run/systemd/journal/syslog
I1108 13:21:25.044886 2636 tail.go:265] openlogPath /run/systemd/journal/syslog false
I1108 13:21:25.045035 2636 log_watcher.go:268] Adding a watch on resolved path "/run/systemd/journal"
I1108 13:21:25.045174 2636 log_watcher.go:253] Found this processor in watched list
I1108 13:21:25.045315 2636 file.go:52] file.New(/run/systemd/journal/syslog, false)
I1108 13:21:25.045454 2636 file.go:111] open failed all retries
W1108 13:21:25.045577 2636 mtail.go:101] attempting to tail "/run/systemd/journal/syslog": open /run/systemd/journal/syslog: no such device or address
...
mtail version and command line
$ sudo mtail --logs /run/systemd/journal/syslog --progs . --logtostderr -v 5
I1108 13:21:25.037480 2636 main.go:100] mtail version v3.0.0-rc33 git revision aedde73f9c304e4d558a53ece22a5472c87a7fdb go version go1.12.7 go arch amd64 go os linux
Related Issues: #58
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 23 (14 by maintainers)
Commits related to this issue
- Open the socket with unix dgram protocol. This seems to work, but can't actually test against my systemd journal yet. Issue #276 — committed to google/mtail by jaqx0r 4 years ago
Great news here, I’ve figured out why mtail isn’t creating sockets to receive logs at all, it’s protected by a code path that is trying to stat the file first so if no socket exists it never gets to the point of trying to listen on it.
I’m going to fix this by requiring the user to specify a prefix like “unixgram:” before the pathname.
Here’s a quick summary of what I’ve learned while building socket support.
traditional
syslog()
sends to/dev/log
, which is a unix domain datagram socket, and normally a syslogd listens on it for logs to then write to whereever.Nowadays on Linux, the
systemd-journal
process handles logs from userspace, kernel, and keeps them in the journal.journalctl
lets you poke around with them, andsystemd-journal
will also forward them on to asyslogd
if one is listening on the correct unix-dgram socket.To receive logs directly from systemd-journal, one must be able to read from a unix domain socket.
mtail
now does this, although I kind of regret it. Socket support for both datagram and stream families was tricky and likely has many future bugs.Normally your distro will have one of
syslog-ng
orrsyslogd
acting as thatsyslogd
, though.I strongly do not recommend
mtail
being the direct listener of/dev/log
or thesystemd
journal.mtail
does not perform any ordinary syslog functions, it merely matches text file inputs and increments counters. The interoperation ofsystemd
and thesyslogd
appears to be a rich API and tools likesyslog-ng
automatically supportsystemd-journal
in the normal course of their role.mtail
doesn’t want to be in the business of specific API interoperation, for at least two reasons: one is binary size as a result of features, and the other is maintenance cost.So, if you want to interoperate
mtail
with syslog, then I suggest using the above syslog daemons to “tee” off the logs you’re interested in:rsyslog supports forwarding to a named pipe and to a unix domain socket
syslog-ng supports output to named pipe and unix domain socket
Configure
mtail
to listen on that pipe or unix domain socket, and you’ll get what you want.mtail
’s filtering is not great – you have to get to the match program before yuo end up discarding log entries, which is expensive in terms of memory copies. With both the above tools you have lots of power for filtering which input gets sent to themtail
pipe.1: Do not replace your syslog with
mtail
, you will lose a lot of functionality and reliability.I also wouldn’t recommend using
mtail
to receive cross-network log traffic. Firstly it’s not lossless, for all the reasons that the rsyslog’s RELP protocol exists.mtail
isn’t that smart;mtail
doesn’t want to be in the business of reliable network transport; it just wants to tail a log stream as fast as possible and turn that into metrics.If I wanted a single
mtail
central service reading logs from multiple remote nodes, I’d usersyslogd
to perform the log transport, and a local named pipe to funnel the bytes from the receiverrsyslogd
tomtail
.2: Do not let
mtail
listen on a network for logs, prefer a reliable log transport option and then a local forward over a Unix named pipe.Why would I recommend a pipe over a socket? The overhead is lower, so the bytes move faster. The read semantics are nearly identical to a file and thus well tested. Sockets are OK but the connection oriented stream now incurs an API cost (we’re now listening on an address anyone can connect to) and complexifies the implementation (multiple connection handlers are possible) and the datagram socket violates the interface by not having any concept of “end of transmission”, though the workaround is a neat hack.
Aha.
The problem is that mtail reads from named pipes, not unix sockets. The code is failing because it’s attempting to open the unix socket /run/systemd/journal/syslog as a named pipe, which fails because there is “no such device or address” called that.
The clue was eventually I read man 7 pipe and then thought “Am I sure the s at the start of the ls before is in fact a named pipe?” and then the ls info page revealing to me it’s in fact a socket…
I have a funny feeling I deleted some code about two years ago that did this.
On Wed, 18 Dec 2019 at 16:24, Jamie Wilkinson jaq@spacepants.org wrote: