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

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

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

阅读logger在 Arch Linux 中将其消息记录到哪里?,似乎syslog消息和命令行应用程序只与日志logger对话systemd是否设置了用于消息转发的套接字

那么这个命令的现代对应词是什么logger如何从命令行直接向 systemd 日志发送消息?

答案1

systemd-cat相当于logger

echo 'hello' | systemd-cat

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

Feb 07 13:38:33 localhost.localdomain cat[15162]: hello

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

echo 'hello' | systemd-cat -p info
echo 'hello' | systemd-cat -p warning
echo 'hello' | systemd-cat -p emerg

警告用粗体字标出,紧急情况用粗体字标出且为红色。很吓人。

您还可以使用任意的“标识符”来指定应用程序名称。这些类似于 syslog 的旧功能,但您不必拘泥于古老的东西,例如lpr uucp nntp或始终具有描述性的local0through local7

echo 'hello' | systemd-cat -t someapp -p emerg

记录为:

Feb 07 13:48:56 localhost.localdomain someapp[15278]: hello

答案2

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

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

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

例子

Ashell 脚本(在这种情况下为 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."

中的设置单元文件通常不需要特别设置。stderr 日志记录开箱即用,除非在全局覆盖systemd-系统配置文件(5)或日志配置文件(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

请注意,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

日志记录级别定义在sd 守护进程(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 */

参考

相关内容