systemd에서 boot_id 값을 빠르게 변경하십시오.

systemd에서 boot_id 값을 빠르게 변경하십시오.

다른 컴퓨터에 보관된 일부 로그 파일을 보는 동안 일부 로그 항목의 __BOOT_ID값이 다르고 그 사이의 시간 간격이 매우 좁은 것을 발견했습니다. 예를 들어 밀리초로 구분된 로그 항목은 서로 다른 __BOOT_ID값을 갖습니다. 이렇게 짧은 간격으로 시스템을 다시 시작할 수 없기 때문에 이는 불가능합니다.

실행하면 journalctl -o verbose --directory <dir path> | grep -B 30 -A 30 -- "-- Reboot --"다음과 같은 실제 예제가 참조되는 것을 볼 수 있습니다. 여기서는 10밀리초 간격으로 로그 이벤트에 대해 서로 다른 두 개의 시작 ID 값이 있습니다.

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) 에 대한 시스템 소스를 보면 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은 메시지를 혼란스럽게 인터리브합니다.

바라보다Lennart Petling의 댓글존재하다시스템 기능 요청 #662(강조):

따라서 재부팅할 때마다 1970년 날짜와 새로운 임의 부팅 ID로 시작하게 됩니다. 시작할 때마다 이런 방식으로 여러 메시지가 생성됩니다.

표시하는 동안 Journalctl은 이제 이 데이터를 보고 인터리브하여 이해하려고 시도합니다. 인터리브 방식은 행을 함께 정렬하고 새 데이터 앞에 이전 데이터를 배치해야 함을 의미합니다. 이를 위해 먼저 일련번호 비교를 시도합니다. 일련 번호는 메모리에 보관되며 부팅할 때마다 0으로 재설정됩니다. 따라서 비교하려는 두 라인 사이의 실행 ID가 일치하는 경우에만 비교할 수 있습니다. 재부팅 시 부팅 ID가 다르기 때문에(분명하고 정확하게) 이 정렬 논리를 사용할 수 없습니다. 다음으로, Journalctl은 단조로운 타임스탬프(즉, 시작 이후 경과된 시간)를 기준으로 항목을 정렬하려고 시도합니다. 이 정렬은 동일한 조건에서만 작동합니다. 즉, 동일한 부팅의 행을 단조로운 시간으로만 정렬할 수 있습니다.이는 벽시계 시간을 통해 두 라인을 비교하는 마지막 접근 방식을 취한다는 것을 의미합니다. 하지만 이것은 항상 1970년입니다. 따라서 보시다시피 인터레이스, 선이 모두 함께 혼합되는 현상이 발생합니다.

이를 확인하는 한 가지 방법은 journalctl --list-boots날짜 범위를 실행하여 확인하는 것입니다. 겹치는 경우 Journalctl은 가짜 타임스탬프를 사용합니다.

관련 정보