如何从命令行向 systemd 日志发送消息?

mik*_*ana 68 logging systemd

在较旧的 Linux 系统中,该logger命令可用于向 syslog 发送日志消息。

阅读在 Arch Linux 中将其消息记录到何处logger如果设置了用于消息转发的套接字syslog消息和logger命令行应用程序似乎只与systemd日志对话。

那么logger命令的现代等价物是什么?如何从命令行直接向 systemd 日志发送消息?

mik*_*ana 97

systemd-cat 相当于记录器:

echo 'hello' | systemd-cat
Run Code Online (Sandbox Code Playgroud)

在另一个终端中,运行journalctl -f

Feb 07 13:38:33 localhost.localdomain cat[15162]: hello
Run Code Online (Sandbox Code Playgroud)

优先级仅由字符串的一部分指定:

echo 'hello' | systemd-cat -p info
echo 'hello' | systemd-cat -p warning
echo 'hello' | systemd-cat -p emerg
Run Code Online (Sandbox Code Playgroud)

警告为粗体,紧急情况为粗体和红色。可怕的东西。

您还可以使用任意的“标识符”来指定应用程序名称。这些就像 syslog 的旧设施,但您不会被像古老的东西lpr uucp nntp或不断描述的local0through 之类的东西困住了local7

echo 'hello' | systemd-cat -t someapp -p emerg
Run Code Online (Sandbox Code Playgroud)

记录为:

Feb 07 13:48:56 localhost.localdomain someapp[15278]: hello
Run Code Online (Sandbox Code Playgroud)

  • 很有用。您可以使用以下命令过滤到使用 `-t` 创建的日志消息:`journalctl -t someapp` (11认同)

kkm*_*ses 9

由于问题提到了 Arch Linux(从第一天起就由 systemd 控制)和日志记录,我猜测它与来自 systemd 服务的日志记录有关。这是从 systemd 服务单元调用的 shell 脚本另一种日志记录技术。systemd 可以(默认情况下)设置为侦听服务的进程 stderr 和/或 stdout,并将消息转发到日志。当消息以 3 个字符的前缀 开头(其中N是 0 到 7 之间的数字)时,systemd 会将其解释为日志级别,忽略它,并在指定级别记录字符串的其余部分。'<' N '>'

这很方便,因为来自任何命令的任何 stderr 消息都会自动记录在错误级别。另一个 fd 保留用于以任意不同的严重性进行日志记录。

这当然适用于所有程序,而不仅仅是 shell 脚本。

例子

一个shell 脚本(在本例中为 Bash,依赖于进程替换和trap ... EXIT行为),取自真实服务的ExecStartPre脚本:

#!/bin/bash

# Redirect stderr such that any message is reported as an error to journald by
# prepending '<3>' to it. Use fd 4 (the saved stderr) to directly report other
# severity levels.
exec 4>&2 2> >(while read -r REPLY; do printf >&4 '<3>%s\n' "$REPLY"; done)

# Systemd can kill the logging subshell swiftly when we exit, and lose messages.
# Close the subshell before exiting the main program explicitly. This will block
# until the read builtin reads the EOF.
trap 'exec >&2-' EXIT

### From this point on, all stderr messages will be logged to syslog as errors
### via the subshell running the while loop. Fd 4 is the old stderr, and may
### be used to specify non-error level:

echo >&2 "This message is logged as an error, red and bold."

echo >&4 "<5>This is logged as a notice-level message, dim and boring."

echo >&4 "This is logged at the default severity level, 'info' unless changed."
Run Code Online (Sandbox Code Playgroud)

单元文件中的设置一般不需要专门设置。stderr 日志记录开箱即用,除非在systemd-system.conf (5) 或journald.conf (5) 中全局覆盖。默认值是:

[Service]
; These defaults may be overridden in systemd-system.conf(5).
;StandardError=journal
;StandardOutput=journal

; These defaults may be overridden in journald.conf(5).
;LogLevelMax=debug
;LogRateLimitIntervalSec=10000
;LogRateLimitBurst=30s

; Extra fields may be added to every message.
;LogExtraFields=

;; Other settings:

; Defaults to process name. NOT the unit name, but rather basename(3) of the $0.
;SyslogIdentifier=

; For messages written without the <N> prefix.
;SyslogLevel=info

;SyslogFacility=daemon

; For completeness only: The level-parsing machinery can be disabled, but that
; was the whole point...
;SyslogLevelPrefix=true
Run Code Online (Sandbox Code Playgroud)

请注意,systemd 会重定向所有通过设置Exec*调用的命令,不仅是主服务进程ExecStart,还包括ExecStartPreExecStartPost等。

要运行该示例,请将上述脚本保存为logging-test.sh,并以 systemd-run 作为临时单元运行,然后查询每个日志记录的完整属性。如果您没有看到信息级别消息,请检查journald.conf 是否将日志中存储的日志记录级别限制为更高的值。

$ systemd-run --user --wait ./logging-test.sh
$ journalctl -t logging-test.sh
$ journalctl -t logging-test.sh -o json-pretty
Run Code Online (Sandbox Code Playgroud)

日志记录级别在sd-daemon (3)中定义:

#define SD_EMERG   "<0>"  /* system is unusable */
#define SD_ALERT   "<1>"  /* action must be taken immediately */
#define SD_CRIT    "<2>"  /* critical conditions */
#define SD_ERR     "<3>"  /* error conditions */
#define SD_WARNING "<4>"  /* warning conditions */
#define SD_NOTICE  "<5>"  /* normal but significant condition */
#define SD_INFO    "<6>"  /* informational */
#define SD_DEBUG   "<7>"  /* debug-level messages */
Run Code Online (Sandbox Code Playgroud)

参考