systemd-journald 持久日志不适用于绑定挂载 /var/log

systemd-journald 持久日志不适用于绑定挂载 /var/log

我正在使用 Yocto 为 SystemD 版本 241 的小型嵌入式 Linux 系统生成自定义映像。根文件系统是只读的。我使用绑定挂载和overlayfs 使 /var/log/journal 目录存在于单独的读/写分区上。我遇到一个问题,systemd-journald 出现“失忆症”并且不记得以前的启动日志,即使它们位于持久读/写文件系统上。这意味着日志无法访问或清除以前启动时的较旧日志文件,即使日志文件在文件系统上存在且有效。

Yocto 挥发性结合

# Setup overlayfs binds for various RW files
VOLATILE_BINDS_append = " \
    /persistent-storage/var/log /var/log\n\
"

路径 /var/log 存在:

root@me:/var/log# cd /var/log/
root@me:/var/log# ls -lrt
total 9
drwxr-xr-x 2 root root            1024 Jun  3 01:50 nginx
-rw-r--r-- 1 root root            5260 Jun  9 17:56 messages
drwxr-sr-x 5 root systemd-journal 1024 Jun  9 18:00 journal
root@me:/var/log# ls -lrt journal/
total 3
drwxr-sr-x 2 root systemd-journal 1024 Jun  9 17:56 5f6085cd81114e8688cf23b3bb91933e
drwxr-sr-x 2 root systemd-journal 1024 Jun  9 17:57 de59603d1ea24e7582ed7d7ed3ac8fb0
drwxr-sr-x 2 root systemd-journal 1024 Jun  9 18:00 0c34cc794e6c4241a75774bbb8324102

我在 /lib/systemd/journald.conf.d/10-persistent-journal.conf 中有一个日志配置文件片段,如下所示:

# By default the maximum use limit (SystemMaxUse) is 10% of the filesystem, and the minimum
# free space (SystemKeepFree) value is 15% - though they are both capped at 4G.
# The journals should be rotated automatically when they reach the SystemMaxFileSize value,
# and the number of journals is controlled by SystemMaxFiles. If you prefer time based
# rotation you can set a MaxFileSec to set the maximum time entries are stored in a single journal.
[Journal]
Storage=persistent
SystemMaxFileSize=128M
SystemMaxFiles=10
SystemMaxUse=256M
SystemKeepFree=256M
SyncIntervalSec=30

问题是,即使我重新启动了几次,journald 成功找到日志并将其写入 /var/log/journal,但它永远找不到以前的日志,并且不知道以前的启动日志。这意味着我无法清理以前的日志,并且我的分区空间不足,即使日志应该保持 50% 的分区空闲。

root@me:/# journalctl --list-boots
0 82fef865e29e481aae27bd247c10e591 Tue 2020-06-09 18:00:12 UTC—Tue 2020-06-09
 18:15:23 UTC

虽然:

root@me:/# ls -lrt /var/log/journal/
total 3
drwxr-sr-x 2 root systemd-journal 1024 Jun  9 17:56 5f6085cd81114e8688cf23b3bb91933e
drwxr-sr-x 2 root systemd-journal 1024 Jun  9 17:57 de59603d1ea24e7582ed7d7ed3ac8fb0
drwxr-sr-x 2 root systemd-journal 1024 Jun  9 18:00 0c34cc794e6c4241a75774bbb8324102

此外,以下命令也有效:

root@me:/# journalctl -b 0
<information>
root@me:/# journalctl -b 1
<information>

root@me:/# journalctl -b 2
Data from the specified boot (+2) is not available: No such boot ID in journal

我读了这篇文章:可以是除 / 之外的文件系统上的日志路径吗?。我尝试了以下挂载文件,但我看到了完全相同的行为:

[Unit]
Description=Persistent Journal Storage Bind

[Mount]
What=/anotherfs/journal
Where=/var/log/journal
Type=none
Options=bind

[Install]
WantedBy=local-fs.target

我做错了什么以及如何让日志在绑定安装系统上使用持久日志?

答案1

我已经和同样的问题斗争了一段时间了。我有一个基于 Yocto 的发行版,其中有一个只读 rootfs,并且 /var/log 文件夹使用 volatile-binds 安装在不同的分区中。一旦我让日志记录到新分区,我注意到同样的事情,journalctl --list-boots只会显示当前的启动,而不是旧的启动。后很多经过反复试验,我终于弄清楚了原因。

正如您所指出的,/var/log/journal显示 3 个文件夹:

root@mir-edb-intel-gen1:~# ls -lrt /var/log/journal/
total 24
drwxr-sr-x+ 2 root systemd-journal 4096 Mar  5 09:24 7f7f3d516b554d718d688a0b0fa9648e
drwxr-sr-x+ 2 root systemd-journal 4096 Mar  5 09:25 93eb74229e9244a4b7f60c90acacc12f
drwxr-sr-x+ 2 root systemd-journal 4096 Mar  5 10:57 4a9652b4b33a4a099bdc6be8c6fb2b1a

并且journalctl --list-boots仅显示 1 个条目:

 0 6cb4f9f236954f69937be217f36c1ce2 Fri 2021-03-05 10:57:48 UTC—Fri 2021-03-05 11:01:22 UTC

但是,如果您运行journalctl -D /var/log/journal --list-boots所有 3 次启动,就会按预期显示:

root@mir-edb-intel-gen1:~# journalctl -D /var/log/journal --list-boots
-2 9ab6d00dea9d41da9c76bf2a3f64895c Fri 2021-03-05 09:24:20 UTC—Fri 2021-03-05 09:25:03 UTC
-1 00509584245d44d599d88db8dccd4177 Fri 2021-03-05 09:25:37 UTC—Fri 2021-03-05 10:14:42 UTC
 0 6cb4f9f236954f69937be217f36c1ce2 Fri 2021-03-05 10:57:48 UTC—Fri 2021-03-05 11:01:22 UTC

虽然我对 systemd 不太了解,但我相信问题是由于我们正在刷新日志/运行/日志/日志/var/log/日志每次我们启动时,而不是向现有登录写入更多内容/var/log/日志。然后,当您调用journalctl它时,它只查看最新的文件夹,因此无法找到以前的启动,除非您专门告诉它查看整个文件夹/var/log/日志

编辑: @贾普·乔里斯·文斯似乎对行为有一个很好的解释这个答案

编辑2: 在我们的例子中,该/etc/machine-id文件是一个空文件,如下所述poky/meta/classes/rootfs-postcommands.bbclass

#
# A hook function to support read-only-rootfs IMAGE_FEATURES
#
read_only_rootfs_hook () {

    [...]

    if ${@bb.utils.contains("DISTRO_FEATURES", "systemd", "true", "false", d)}; then
    # Create machine-id
    # 20:12 < mezcalero> koen: you have three options: a) run systemd-machine-id-setup at install time, b) have / read-only and an empty file there (for stateless) and c) boot with / writable
        touch ${IMAGE_ROOTFS}${sysconfdir}/machine-id
    fi
}

答案2

Systemd-Journald在系统启动的早期阶段启动您的mount/var/log)可能会在服务启动后发生 /var/log。需要有关如何挂载 RW 分区的更多详细信息。

您可以尝试jounrald在系统启动后重新启动该服务。

Storage= 控制日志数据的存储位置。 “易失性”、“持久性”、“自动”和“无”之一。如果为“易失性”,日志日志数据将仅存储在内存中,即在 /run/log/journal 层次结构(如果需要时创建)之下。如果“持久”,数据将优先存储在磁盘上,即在 /var/log/journal 层次结构(如果需要时创建)下方,并回退到 /run/log/journal(如果需要则创建),早期启动以及磁盘不可写。 “auto”与“persistent”类似,但如果需要,不会创建目录 /var/log/journal,因此它的存在控制着日志数据的去向。 “none”关闭所有存储,接收到的所有日志数据都将被丢弃。不过,转发到其他目标(例如控制台、内核日志缓冲区或系统日志套接字)仍然有效。在默认日志命名空间中默认为“auto”,在所有其他命名空间中默认为“persistent”。

此处提供更多信息:链接1,链接2,链接3,链接3,链接5,链接6,链接7

答案3

可能的解决方法是从 /var/log/journal 到另一个分区的符号链接。

在我的只读 rootfs Yocto 系统上,我在启动应用程序的 systemd 服务之一中设置了此符号链接。在符号链接到位之前,所有日志都会进入 RAM,然后刷新到符号链接分区。

mkdir -p /data/log/journal
systemd-tmpfiles --create --prefix /data/log/journal
ln -s /data/log/journal /var/log/journal
journalctl --flush

答案4

创建日志/run/log/journal/后是否仍会写入?/var/log/journal/如果是这样,它仍然可以从 易失性目录中读取/run/

您是否更改了 running# journalctl --list-boots和之间的另一个参数# journalctl -b 1?因为从你的输出来看,它似乎正在从一个不存在的文件中读取。无论你跑步时的配置如何,# journalctl -b 1似乎都会保持持久性。

抱歉,我认为这作为评论比答案更合适,但我还没有足够的声誉来发表评论。

相关内容