快速更改 systemd 中的 boot_id 值

快速更改 systemd 中的 boot_id 值

在查看另一台计算机上的一些存档日志文件时,我注意到一些日志条目具有不同的__BOOT_ID值,并且它们之间的时间间隔极窄。例如,间隔毫秒的日志条目将具有不同的__BOOT_ID值。这是不可能的,因为机器无法在这么小的时间间隔内重新启动。

当我运行时,journalctl -o verbose --directory <dir path> | grep -B 30 -A 30 -- "-- Reboot --"我可以看到引用以下真实示例,其中有两个不同的启动 ID 值用于间隔 10 毫秒的日志事件。

Wed 2019-11-13 21:35:58.469925 ...
    _TRANSPORT=kernel
    PRIORITY=6
    SYSLOG_FACILITY=0
    SYSLOG_IDENTIFIER=kernel
    _BOOT_ID=fec227a60ef24474aacd023d6c02733f
...
...
...
    MESSAGE=spi1.0: ttyMAX1 at I/O 0x20 (irq = 30, base_baud = 3000000) is a MAX3109
-- Reboot --
Wed 2019-11-13 21:35:58.470352 ...
    _SOURCE_MONOTONIC_TIMESTAMP=0
    _TRANSPORT=kernel
    PRIORITY=6
    SYSLOG_FACILITY=0
    SYSLOG_IDENTIFIER=kernel
    MESSAGE=Booting Linux on physical CPU 0x0
    _BOOT_ID=21b95aabab034009a19d1b7deac80327
...
...
...

我试图寻找可能导致启动 ID 快速更改的原因,但没有成功。查看版本 ( v243) 的 systemd 源表明sd_id128_get_boot()这似乎是用于读取启动 ID 的函数只是从文件中读取内核生成的值


        if (sd_id128_is_null(saved_boot_id)) {
                r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id);
                if (r < 0)
                        return r;
        }

        *ret = saved_boot_id;
        return 0;

最终结果是日志中显示的重新启动列表,但最终可能不会重新启动。有趣的是,journalctl --list-boots根本不会将这些显示为重新启动(当前正在尝试了解get_boots()实现)。

如果有人之前看到过这种行为,请感谢任何想法和意见。我知道这jounalctl --list-boots是获取重新启动列表的地方,但我正在尝试使用一组特定的重新启动信息来分析日志。这些误报污染了我尝试编写的脚本的结果。

答案1

我不认为启动 ID 实际上变化得那么快。我认为您同时查看来自多个不同靴子的日志,并且它们混合在一起。

如果您的系统没有电池供电的实时时钟,则可能会发生这种情况。

Journalctl 使用挂钟时间对来自不同启动的日志消息进行排序。如果挂钟在每次启动时重置,则看起来来自不同启动的消息是同时发生的,并且journalctl会将它们混淆地交错。

伦纳特·珀特林的评论systemd 功能请求 #662(强调我的):

因此,会发生以下情况:每次重新启动时,都会以 1970 年的日期和新随机的启动 ID 开始。每次启动时都会以这种方式生成几条消息。

在显示期间,journalctl 现在将看到此数据,并尝试理解它,并交错它。交错意味着它需要将行排序在一起,并将旧数据放在新数据之前。为此,它首先尝试比较序列号。序列号保存在内存中,并在每次启动时重置为零。因此,只有当要比较的两条线之间的启动 ID 匹配时,才能比较它们。由于重新启动时启动 ID 不同(显然且正确),因此无法使用这种排序逻辑。接下来,journalctl 尝试按单调时间戳(即自启动以来经过的时间)对事物进行排序。这种排序仅在相同条件下有效:我们只能通过单调时间对同一引导的行进行排序。这意味着我们采用最后一种方法来比较两条线:通过挂钟时间。但这始终是 1970 年,因此会导致您看到的交错,线条全部混合在一起。

确认这一点的一种方法是运行journalctl --list-boots并检查日期范围。如果它们重叠,则journalctl正在使用伪造的时间戳。

相关内容