我想在临时单元中运行一个程序systemd-run
, 使用用户级服务管理器(--user
),其中有一些自定义字段附加到日志中。
根据文档我可以用来LogExtraFields
做这个。所以我运行程序并设置自定义字段FOO=bar
,如下所示:
$ systemd-run --user --property LogExtraFields="FOO=bar" sh -c "sleep 1 && echo henlo"
但是当我检查临时单元的日记帐分录时,我的自定义标签不存在:
$ journalctl --user-unit run-rd8f0b861d11d4b13bcdae84e5a9d55cf.service -o verbose | grep FOO
$
然而,当我尝试同样的操作时根并使用系统级服务经理,我的自定义字段确实写入了日志:
$ sudo systemd-run --property LogExtraFields="FOO=bar" \
sh -c "sleep 1 && echo henlo"
$ sudo journalctl --unit run-r75220e0f4e574ba292eb864c65d7f414.service -o verbose | grep FOO
FOO=bar
为什么会这样?用户是否需要额外的权限才能将额外的字段写入日记帐?
答案1
为什么会这样?用户是否需要额外的权限才能将额外的字段写入日记帐?
用户不知道,但具体机制systemd 用于向 journald 提供额外字段,至少目前,只知道系统级单元(并且依赖于对 /run/systemd 的写访问权限)。
尽管你的用户级 systemd 管理器可以直接向 journald 提供额外字段,在为此服务创建 stdout-to-journal 管道时,这只会对从 stdout 和 stderr 捕获的消息产生影响 - 但如果服务进程本身通过 /dev/log 或通过“主”journald 日志套接字提交消息,则无法自动附加这些字段。
为了解决这个问题,systemd 选择让 journald 手动向 systemd 查询附加到该单元的额外字段(因为 journald 已经知道1该进程属于哪个单元)——但按照目前的实现,只有系统范围的服务管理器 (pid1) 被查询附加到[电子邮件保护];您的用户级服务将被忽略。
1(对于诸如此类的短暂进程,echo
还存在一个问题,即在 journald 找出其所属单元之前,进程就已经退出。与内核附加到每个套接字消息的 PID 或 UID 不同,内核开发人员坚决拒绝附加 cgroup 成员资格数据,因此 journald 需要在事后从 /proc/<pid> 获取它。这就是为什么您可能会看到_SYSTEMD_UNIT=
某些消息中缺少这些信息的原因。)
如果用户进程直接通过主 journald 套接字提交消息,则可以包含自定义字段(特权_*
字段除外)。(这已经由 GLib2 日志记录函数完成。)例如:
logger --journald <<EOF
MESSAGE=Hello!
FOO=bar
EOF
(--sd-param
如果您在手册中找到该选项,请忽略它;“sd”不是指 systemd – 它是 RFC 5424“IETF Syslog”协议中的结构化数据。)